rename project and game to RhythmBullet

This commit is contained in:
2017-07-31 00:06:10 -05:00
parent db27f7dbae
commit 54c61fcba5
91 changed files with 234 additions and 743 deletions

View File

@@ -0,0 +1,290 @@
package zero1hd.rhythmbullet;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.assets.loaders.ParticleEffectLoader;
import com.badlogic.gdx.assets.loaders.SoundLoader;
import com.badlogic.gdx.assets.loaders.TextureAtlasLoader;
import com.badlogic.gdx.assets.loaders.TextureLoader;
import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver;
import com.badlogic.gdx.assets.loaders.resolvers.ResolutionFileResolver.Resolution;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.ui.Button.ButtonStyle;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.ui.List.ListStyle;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane.ScrollPaneStyle;
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox.SelectBoxStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider.SliderStyle;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
import com.badlogic.gdx.scenes.scene2d.ui.TextField.TextFieldStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;
import zero1hd.rhythmbullet.screens.LoadingScreen;
import zero1hd.rhythmbullet.screens.MainMenu;
import zero1hd.rhythmbullet.util.GenericFileTypeHandler;
import zero1hd.rhythmbullet.util.RoundingResolutionHandler;
public class Main extends Game {
private boolean initComplete = false;
public static final int GAME_AREA_WIDTH = 64;
public static final int GAME_AREA_HEIGHT = 48;
public static final String VERSION = "(0.1)R1-PreAlpha";
private AssetManager assetManager = new AssetManager();
private Skin defaultSkin = new Skin();
private FreeTypeFontGenerator default_fontGenerator;
private FreeTypeFontGenerator darktech_ldr_fontGenerator;
TextureAtlas skinAtlas;
private Preferences prefs;
@Override
public void create() {
Gdx.app.setLogLevel(Application.LOG_DEBUG);
prefs = Gdx.app.getPreferences("PolyJet_Preferences");
if (prefs.getBoolean("fullscreen", true)) {
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
} else {
Gdx.graphics.setWindowedMode(prefs.getInteger("screen-width"), prefs.getInteger("screen-height"));
}
Gdx.app.debug("Prelaunch Debug Info", "\ncurrent window size: "
+ Gdx.graphics.getWidth() + "x" + Gdx.graphics.getHeight() +"\n"
+ "Pixel density (PPI): " + Gdx.graphics.getDensity());
setScreen(new MainMenu(this));
Resolution[] resolution = {
new Resolution(800, 480, "800x480"),
new Resolution(1280, 720, "1280x720"),
new Resolution(1366, 768, "1366x768"),
new Resolution(1280, 800, "1280x800"),
new Resolution(1920, 1080, "1920x1080"),
new Resolution(1920, 1200, "1920x1200"),
new Resolution(2560, 1440, "2560x1440"),
new Resolution(3840, 2160, "3840x2160"),
};
InternalFileHandleResolver internalFileResolver = new InternalFileHandleResolver();
RoundingResolutionHandler rRHandler = new RoundingResolutionHandler(internalFileResolver, resolution);
GenericFileTypeHandler genericFileFinder = new GenericFileTypeHandler(internalFileResolver);
assetManager.setLoader(TextureAtlas.class, new TextureAtlasLoader(rRHandler));
assetManager.setLoader(Texture.class, new TextureLoader(rRHandler));
assetManager.setLoader(ParticleEffect.class, new ParticleEffectLoader(genericFileFinder));
assetManager.setLoader(Sound.class, new SoundLoader(genericFileFinder));
default_fontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/Gasalt-Regular.ttf"));
darktech_ldr_fontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/darktech_ldr.ttf"));
}
@Override
public void render() {
super.render();
}
@Override
public void dispose() {
if (skinAtlas != null) {
skinAtlas.dispose();
getDefaultSkin().dispose();
default_fontGenerator.dispose();
darktech_ldr_fontGenerator.dispose();
assetManager.dispose();
}
super.dispose();
}
public void queueAssets() {
assetManager.load("uiskin.atlas", TextureAtlas.class);
assetManager.load("Tech-Circle1.png", Texture.class);
assetManager.load("polyjet-standard.png", Texture.class);
assetManager.load("standard_thrust.p", ParticleEffect.class);
assetManager.load("keyboard.atlas", TextureAtlas.class);
assetManager.load("cybercircle3B.png", Texture.class);
assetManager.load("PolyjetTitle.png", Texture.class);
assetManager.load("cybercircle1.png", Texture.class);
assetManager.load("defaultCover.png", Texture.class);
assetManager.load("teleport-cloak.p", ParticleEffect.class);
assetManager.load("pop_open.ogg", Sound.class);
assetManager.load("pop_close.ogg", Sound.class);
assetManager.load("laser.png", Texture.class);
assetManager.load("pellet.png", Texture.class);
assetManager.load("shard.png", Texture.class);
assetManager.load("bar.png", Texture.class);
assetManager.load("flake.png", Texture.class);
assetManager.load("star_bg.png", Texture.class);
assetManager.load("void_circle.png", Texture.class);
assetManager.load("laser.ogg", Sound.class);
assetManager.load("explosion.ogg", Sound.class);
assetManager.load("disintegrate.ogg", Sound.class);
assetManager.load("explosion-s.p", ParticleEffect.class);
assetManager.load("tpSelector.png", Texture.class);
assetManager.load("magic1.png", Texture.class);
}
public void generateFonts() {
initComplete = true;
defaultSkin = new Skin();
Gdx.app.debug("Prelaunch Debug Info", "Generating fonts...");
skinAtlas = assetManager.get("uiskin.atlas", TextureAtlas.class);
getDefaultSkin().addRegions(skinAtlas);
getDefaultSkin().add("window-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
{
size = 18;
}
}));
getDefaultSkin().add("sub-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
{
size = fontScale(0.04f);
}
}));
getDefaultSkin().add("default-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
{
size = fontScale(0.07f);
}
}));
getDefaultSkin().add("large-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
{
size = fontScale(0.085f);
}
}));
getDefaultSkin().add("special-font", darktech_ldr_fontGenerator.generateFont(new FreeTypeFontParameter() {
{
size = fontScale(0.075f);
}
}));
}
public void defineSkinStyles() {
getDefaultSkin().add("default", Color.BLACK);
getDefaultSkin().add("inverse", Color.WHITE);
TextButtonStyle defaultTextButton = new TextButtonStyle();
defaultTextButton.up = getDefaultSkin().getDrawable("default-round");
defaultTextButton.down = getDefaultSkin().getDrawable("default-round-down");
defaultTextButton.font = getDefaultSkin().getFont("default-font");
defaultTextButton.fontColor = getDefaultSkin().getColor("default");
defaultTextButton.disabled = getDefaultSkin().getDrawable("default-round-disabled");
getDefaultSkin().add("default", defaultTextButton);
TextButtonStyle subTextbutton = new TextButtonStyle(defaultTextButton);
subTextbutton.font = getDefaultSkin().getFont("sub-font");
getDefaultSkin().add("sub", subTextbutton);
TextButtonStyle textButtonLeft = new TextButtonStyle();
textButtonLeft.up = getDefaultSkin().getDrawable("left-button");
textButtonLeft.down = getDefaultSkin().getDrawable("left-button-down");
textButtonLeft.font = getDefaultSkin().getFont("default-font");
textButtonLeft.fontColor = getDefaultSkin().getColor("default");
getDefaultSkin().add("left", textButtonLeft);
SliderStyle defaultSlider = new SliderStyle(getDefaultSkin().getDrawable("default-slider"), getDefaultSkin().getDrawable("default-slider-knob"));
getDefaultSkin().add("default-horizontal", defaultSlider);
SliderStyle vertSlider = new SliderStyle(defaultSlider);
vertSlider.knob = getDefaultSkin().getDrawable("vertical-slider-knob");
getDefaultSkin().add("default-vertical", vertSlider);
ButtonStyle infoButton = new ButtonStyle();
infoButton.up = getDefaultSkin().getDrawable("holo-pane");
infoButton.down = getDefaultSkin().getDrawable("holo-pane-down");
getDefaultSkin().add("info-button", infoButton);
LabelStyle defaultLabel = new LabelStyle();
defaultLabel.font = getDefaultSkin().getFont("default-font");
defaultLabel.fontColor = getDefaultSkin().getColor("default");
getDefaultSkin().add("default", defaultLabel);
TextFieldStyle defaultTextField = new TextFieldStyle(getDefaultSkin().getFont("sub-font"), getDefaultSkin().getColor("default"), getDefaultSkin().getDrawable("cursor"), getDefaultSkin().getDrawable("selection"), getDefaultSkin().getDrawable("textfield"));
getDefaultSkin().add("default", defaultTextField);
TextFieldStyle uiTextField = new TextFieldStyle(defaultTextField);
uiTextField.font = getDefaultSkin().getFont("window-font");
getDefaultSkin().add("ui", uiTextField);
WindowStyle defaultWindow = new WindowStyle(getDefaultSkin().getFont("window-font"), getDefaultSkin().getColor("default"), getDefaultSkin().getDrawable("default-window"));
getDefaultSkin().add("default", defaultWindow);
WindowStyle tintedWindow = new WindowStyle(defaultWindow);
tintedWindow.titleFontColor = getDefaultSkin().getColor("inverse");
tintedWindow.background = getDefaultSkin().getDrawable("tinted-window");
getDefaultSkin().add("tinted", tintedWindow);
ListStyle defaultList = new ListStyle(getDefaultSkin().getFont("window-font"), getDefaultSkin().getColor("inverse"), getDefaultSkin().getColor("default"), getDefaultSkin().getDrawable("selection"));
getDefaultSkin().add("default", defaultList);
ScrollPaneStyle defaultScrollPane = new ScrollPaneStyle();
defaultScrollPane.vScroll = getDefaultSkin().getDrawable("default-scroll");
defaultScrollPane.hScrollKnob = getDefaultSkin().getDrawable("default-round-large");
defaultScrollPane.hScroll = getDefaultSkin().getDrawable("default-scroll");
defaultScrollPane.vScrollKnob = getDefaultSkin().getDrawable("default-round-large");
getDefaultSkin().add("default", defaultScrollPane);
CheckBoxStyle defaultCheckBox = new CheckBoxStyle(getDefaultSkin().getDrawable("check-off"), getDefaultSkin().getDrawable("check-on"), getDefaultSkin().getFont("window-font"), getDefaultSkin().getColor("default"));
getDefaultSkin().add("default", defaultCheckBox);
CheckBoxStyle expandableCheckBox = new CheckBoxStyle(defaultCheckBox);
expandableCheckBox.font = getDefaultSkin().getFont("sub-font");
getDefaultSkin().add("expandable", expandableCheckBox);
SelectBoxStyle defaultSelectBox = new SelectBoxStyle(getDefaultSkin().getFont("default-font"), getDefaultSkin().getColor("default"), getDefaultSkin().getDrawable("default-select"), defaultScrollPane, defaultList);
getDefaultSkin().add("default", defaultSelectBox);
Gdx.app.debug("Prelaunch Debug Info", "UI Skin has been defined.");
}
@Override
public void resize(int width, int height) {
if (initComplete) {
getDefaultSkin().dispose();
assetManager.clear();
prefs.putInteger("screen-width", width);
prefs.putInteger("screen-height", height);
prefs.flush();
}
setScreen(new LoadingScreen(this, getScreen(), true, !initComplete));
super.resize(width, height);
}
public int fontScale(float fontSize) {
Gdx.app.debug("Font pixel size", MathUtils.round(Gdx.graphics.getDensity()*(fontSize*Gdx.graphics.getHeight())) + "px");
return MathUtils.round(Gdx.graphics.getDensity()*(fontSize*Gdx.graphics.getHeight()));
}
public AssetManager getAssetManager() {
return assetManager;
}
public Skin getDefaultSkin() {
return defaultSkin;
}
public Preferences getPrefs() {
return prefs;
}
}

View File

@@ -0,0 +1,15 @@
package zero1hd.rhythmbullet.audio;
import com.badlogic.gdx.files.FileHandle;
public class Audio {
public static AudioData getAudioData(FileHandle file) {
if (file.extension().equalsIgnoreCase("wav")) {
return new WavAudioData(file);
} else if (file.extension().equalsIgnoreCase("mp3")) {
return new Mp3AudioData(file);
}
return null;
}
}

View File

@@ -0,0 +1,418 @@
package zero1hd.rhythmbullet.audio;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.FloatArray;
import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniSender;
public class AudioAnalyzer {
private boolean containsData;
private boolean finalized;
FloatFFT_1D fft;
public AudioData audioData;
float[] audioPCM;
float[] spectrum;
float[] lastSpectrum;
Runnable analysisAlgorithm;
Runnable thresholdCalculator;
int bassBinBegin;
int bassBinEnd;
private FloatArray bassSpectralFlux = new FloatArray();
private FloatArray bassThreshold = new FloatArray();
private FloatArray bassPrunned = new FloatArray();
private FloatArray bassPeaks = new FloatArray();
private float bassMaxValue;
private float bassAvg;
float bassThresholdMultiplier;
int bassThresholdCalcRange;
int mBinBegin;
int mBinEnd;
private FloatArray mSpectralFlux = new FloatArray();
private FloatArray mThreshold = new FloatArray();
private FloatArray mPrunned = new FloatArray();
private FloatArray mPeaks = new FloatArray();
private float mMaxValue;
private float mAvg;
float mThresholdMultiplier;
int mThresholdCalcRange;
int umBinBegin;
int umBinEnd;
private FloatArray umSpectralFlux = new FloatArray();
private FloatArray umThreshold = new FloatArray();
private FloatArray umPrunned = new FloatArray();
private FloatArray umPeaks = new FloatArray();
private float umMaxValue;
private float umAvg;
float umThresholdMultiplier;
int umThresholdCalcRange;
public volatile MiniSender sender;
private float avgSPB;
int PUID;
boolean work;
private volatile int progress;
private float secondsPerWindow;
public AudioAnalyzer() {
sender = new MiniSender();
analysisAlgorithm = new Runnable() {
@Override
public void run() {
progress = 0;
int tasksDone = 0;
int totalTasks = audioData.getSampleCount()/audioData.getReadWindowSize();
bassThresholdMultiplier = 1.5f;
mThresholdMultiplier = 1.4f;
umThresholdMultiplier = 1.4f;
bassBinBegin = 0;
bassBinEnd = 12;
mBinBegin = 50;
mBinEnd = 250;
umBinBegin = 350;
umBinEnd = 513;
bassThresholdCalcRange = thresholdRangeCalc(0.27f);
mThresholdCalcRange = thresholdRangeCalc(0.4f);
umThresholdCalcRange = thresholdRangeCalc(0.4f);
Gdx.app.debug("Read freq", String.valueOf(audioData.getFormat().getSampleRate()));
Gdx.app.debug("Using following bin ranges", "\nBass freq begin: " + bassBinBegin + "\nBass freq end: " + bassBinEnd + "\nMain freq begin: " + umBinBegin + "\nMain freq end: " + umBinEnd);
Gdx.app.debug("Threshold Calc Range UM", String.valueOf(umThresholdCalcRange));
Gdx.app.debug("Threshold Calc Range M", String.valueOf(umThresholdCalcRange));
Gdx.app.debug("Threshold Calc Range Bass", String.valueOf(bassThresholdCalcRange));
fft = new FloatFFT_1D(audioData.getReadWindowSize());
int seedDigit = 0;
while (audioData.readSamples(audioPCM) > 0 && work) {
fft.realForward(audioPCM);
//Building a PUID (Pseudo unique ID)
if (tasksDone == (seedDigit*totalTasks/9)) {
float avg = 0;
for (int frame = 0; frame < spectrum.length; frame++) {
avg += spectrum[frame];
}
avg /= spectrum.length;
if (avg < 0) {
avg *= -1f;
}
PUID +=(int) Math.pow(10, 9-seedDigit) * ((int)(avg*1000f)-(int)(avg*100f)*10);
seedDigit ++;
}
System.arraycopy(spectrum, 0, lastSpectrum, 0, spectrum.length);
System.arraycopy(audioPCM, 0, spectrum, 0, spectrum.length);
float fluxVal;
//bass detection
fluxVal = 0;
for (int i = bassBinBegin; i < bassBinEnd && work; i++) {
fluxVal += ((spectrum[i] - lastSpectrum[i])) < 0
? 0 : (spectrum[i] - lastSpectrum[i]);
}
bassSpectralFlux.add(fluxVal);
//m detection
fluxVal = 0;
for (int i = mBinBegin; i < mBinEnd && work; i++) {
fluxVal += ((spectrum[i] - lastSpectrum[i])) < 0
? 0 : (spectrum[i] - lastSpectrum[i]);
}
mSpectralFlux.add(fluxVal);
//um detection
fluxVal = 0;
for (int i = umBinBegin; i < umBinEnd && work; i++) {
fluxVal += ((spectrum[i] - lastSpectrum[i])) < 0
? 0 : (spectrum[i] - lastSpectrum[i]);
}
umSpectralFlux.add(fluxVal);
tasksDone++;
progress = (int) (100f*tasksDone/totalTasks);
sender.send(MiniEvents.ANALYZER_ITERATED);
}
if (work) {
Gdx.app.debug("Audio Analyzer", "Done getting spectral flux.");
Gdx.app.debug("Audio Analyzer", "window count: " + bassSpectralFlux.size);
shrinkData();
containsData = true;
Gdx.app.debug("Audio Analyzer", "USING SEED: " + PUID);
sender.send(MiniEvents.SPECTRAL_FLUX_DONE);
}
}
};
thresholdCalculator = new Runnable() {
@Override
public void run() {
Gdx.app.debug("Audio Analyzer", "beginning thrshold calc.");
//threshold calculation
for (int i = 0; i < umSpectralFlux.size && work; i++) {
int start = Math.max(0, i - umThresholdCalcRange/2);
int end = Math.min(umSpectralFlux.size - 1, i + umThresholdCalcRange/2);
float average = 0;
for (int j = start; j <= end; j++) {
average += bassSpectralFlux.get(j);
}
average /= (end - start);
bassThreshold.add(average * bassThresholdMultiplier);
average = 0;
for (int j = start; j <= end; j++) {
average+= mSpectralFlux.get(j);
}
average /= (end - start);
mThreshold.add(average*mThresholdMultiplier);
average = 0;
for (int j = start; j <= end; j++) {
average+= umSpectralFlux.get(j);
}
average /= (end - start);
umThreshold.add(average*umThresholdMultiplier);
}
Gdx.app.debug("Audio Analyzer", "Threshold calculated.");
//pruning data
float prunnedCurrentVal;
for (int i = 0; i < umSpectralFlux.size && work; i++) {
prunnedCurrentVal = bassSpectralFlux.get(i) - bassThreshold.get(i);
if (prunnedCurrentVal >= 0) {
bassPrunned.add(prunnedCurrentVal);
} else {
bassPrunned.add(0);
}
prunnedCurrentVal = mSpectralFlux.get(i) - mThreshold.get(i);
if (prunnedCurrentVal >= 0 ) {
mPrunned.add(prunnedCurrentVal);
} else {
mPrunned.add(0);
}
prunnedCurrentVal = umSpectralFlux.get(i) - umThreshold.get(i);
if (prunnedCurrentVal >= 0 ) {
umPrunned.add(prunnedCurrentVal);
} else {
umPrunned.add(0);
}
}
Gdx.app.debug("Audio Analyzer", "Data prunned.");
secondsPerWindow = audioData.getReadWindowSize()/audioData.getFormat().getSampleRate();
//peak detection
int lastID = 0;
float bassBeats = 0;
float mBeats = 0;
float umBeats = 0;
avgSPB = -1f;
for (int i = 0; i < umPrunned.size-1 && work; i++) {
bassPeaks.add((bassPrunned.get(i) > bassPrunned.get(i+1) ? bassPrunned.get(i) : 0f));
if (bassPeaks.get(i) > bassMaxValue) {
bassMaxValue = bassPeaks.get(i);
}
mPeaks.add((mPrunned.get(i) > mPrunned.get(i+1) ? mPrunned.get(i) : 0f));
if (mPeaks.get(i) > mMaxValue) {
mMaxValue = mPeaks.get(i);
}
umPeaks.add((umPrunned.get(i) > umPrunned.get(i+1) ? umPrunned.get(i) : 0f));
if (umPeaks.get(i) > umMaxValue) {
umMaxValue = umPeaks.get(i);
}
if (avgSPB != -1) {
if (bassPeaks.get(i) == 0) {
avgSPB ++;
} else {
lastID = i;
}
} else if (bassPeaks.get(i) != 0) {
avgSPB = 0;
}
if (bassPeaks.get(i) != 0) {
bassAvg += bassPeaks.get(i);
bassBeats++;
}
if (mPeaks.get(i) != 0) {
mAvg += mPeaks.get(i);
mBeats++;
}
if (umPeaks.get(i) != 0) {
umAvg += umPeaks.get(i);
umBeats++;
}
}
//then we minus one from the beats so it actually works out
avgSPB -= bassPrunned.size-lastID;
avgSPB *= secondsPerWindow;
avgSPB /= bassBeats;
Gdx.app.debug("Audio Analyzer", "Avg SPB: " + avgSPB);
bassAvg /= bassBeats;
mAvg /= mBeats;
umAvg /= umBeats;
Gdx.app.debug("Audio Analyzer", "Avg bass: " + bassAvg);
Gdx.app.debug("Audio Analyzer", "Avg M: " + mAvg);
Gdx.app.debug("Audio Analyzer", "Avg UM: " + umAvg);
if (work) {
finalized = true;
sender.send(MiniEvents.MUSIC_DATA_CLEANED);
}
}
};
}
public void shrinkData() {
bassSpectralFlux.shrink();
bassThreshold.shrink();
bassPrunned.shrink();
bassPeaks.shrink();
mSpectralFlux.shrink();
mThreshold.shrink();
mPrunned.shrink();
mPeaks.shrink();
umSpectralFlux.shrink();
umThreshold.shrink();
umPrunned.shrink();
umPeaks.shrink();
}
public void startAnalyticalThread(AudioData audiofile) {
audioPCM = new float[audiofile.getReadWindowSize()];
spectrum = new float[(audiofile.getReadWindowSize()/2)+1];
lastSpectrum = new float[(audiofile.getReadWindowSize()/2)+1];
this.audioData = audiofile;
work = true;
Thread analyticalThread = new Thread(analysisAlgorithm);
analyticalThread.start();
}
public void runThresholdCleaning(float rangeModifier) {
this.bassThresholdMultiplier -= rangeModifier;
this.umThresholdMultiplier -= rangeModifier;
work = true;
Thread thresholdClean = new Thread(thresholdCalculator);
thresholdClean.start();
}
public void runThresholdCleaning() {
Thread thresholdClean = new Thread(thresholdCalculator);
thresholdClean.start();
}
public FloatArray getBassPeaks() {
return bassPeaks;
}
public FloatArray getmPeaks() {
return mPeaks;
}
public FloatArray getUMPeaks() {
return umPeaks;
}
private int thresholdRangeCalc(float durationOfRange) {
return (int) (durationOfRange/(audioData.getReadWindowSize()/audioData.getFormat().getSampleRate()));
}
public float getBassMaxValue() {
return bassMaxValue;
}
public float getmMaxValue() {
return mMaxValue;
}
public float getUMMaxValue() {
return umMaxValue;
}
public int getReadIndex() {
if (audioData.getReadIndex() < umPeaks.size) {
return audioData.getReadIndex();
} else {
return 0;
}
}
public boolean containsData() {
return containsData;
}
public synchronized int getProgress() {
return progress;
}
public boolean isFinalized() {
return finalized;
}
public void stop() {
work = false;
}
public int getPUID() {
return PUID;
}
public AudioData getAudioData() {
return audioData;
}
public float getAvgSPB() {
return avgSPB;
}
public float getsecondsPerWindow() {
return secondsPerWindow;
}
public float getBassAvg() {
return bassAvg;
}
public float getUmAvg() {
return umAvg;
}
public float getmAvg() {
return mAvg;
}
}

View File

@@ -0,0 +1,62 @@
package zero1hd.rhythmbullet.audio;
import javax.sound.sampled.AudioFormat;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.utils.Disposable;
public interface AudioData extends Disposable {
/**
* sets a integer variable to the current window of audio data the playback is at.
* Useful for efficiency because we compute once for that frame then get the values everytime it is required instead of calculating every time we get the index.
*/
public void readIndexUpdate();
/**
* Gets the current position in seconds
* @return the current frame of audio.
*/
public int getReadIndex();
/**
* Completely resets the current audio data. Think of pooling, except, only one instance which is reused instead of multiple.
*/
public void reset();
/**
* returns the read window size.
* @return
*/
public int getReadWindowSize();
/**
* Gets the object to play the music. Contains playback data.
* @return
*/
public Music getPlaybackMusic();
/**
* read in samples and fills the array.
* @param samples the array that should contain said samples
* @return amount read. Will return 0 if end of stream.
*/
public int readSamples(float[] samples);
/**
* Returns properly setup AudioFormat object.
* @return
*/
public AudioFormat getFormat();
/**
* returns sample count
* @return
*/
public int getSampleCount();
/**
* returns duration of song in seconds
* @return
*/
public float getDuration();
}

View File

@@ -0,0 +1,124 @@
package zero1hd.rhythmbullet.audio;
import java.io.IOException;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.audio.mp3.MP3File;
import org.jaudiotagger.audio.wav.WavTag;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.TagException;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.Disposable;
public class AudioInfo implements Disposable {
private long durationInSeconds;
private String songName;
private Texture albumCover;
private String author;
private int previousTop;
private int ratedDifficulty;
private byte[] albumWorkBytes;
private boolean invalidMusic;
public AudioInfo(FileHandle musicFile, Preferences musicData) {
if (musicFile.extension().toLowerCase().equals("mp3")) {
MP3File mp3File;
try {
mp3File = new MP3File(musicFile.file());
durationInSeconds = mp3File.getAudioHeader().getTrackLength();
if (mp3File.getTag() != null && mp3File.getTag().getFirstArtwork() != null) {
albumWorkBytes = mp3File.getTag().getFirstArtwork().getBinaryData();
}
songName = mp3File.getTag().getFirst(FieldKey.TITLE);
author = mp3File.getTag().getFirst(FieldKey.ARTIST);
} catch (IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// invalidMusic = true;
} else {
try {
AudioFile audioFile = AudioFileIO.read(musicFile.file());
WavTag wavTag = (WavTag) AudioFileIO.read(musicFile.file()).getTag();
songName = wavTag.getFirst(FieldKey.TITLE);
author = wavTag.getFirst(FieldKey.ARTIST);
durationInSeconds = audioFile.getAudioHeader().getTrackLength();
} catch (CannotReadException | IOException | TagException | ReadOnlyFileException
| InvalidAudioFrameException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (durationInSeconds > 60 * 5) {
invalidMusic = true;
}
if (songName == null || songName.isEmpty()) {
songName = musicFile.nameWithoutExtension();
}
previousTop = musicData.getInteger(songName + ":previous top", -1);
ratedDifficulty = musicData.getInteger(songName + ":difficulty", -1);
if (author == null || author.isEmpty()) {
author = "N/A";
}
}
public void setupTexture(Texture defaultAlbumCover) {
if (albumWorkBytes != null) {
Pixmap albumCoverFromBytes = new Pixmap(albumWorkBytes, 0, albumWorkBytes.length);
albumCover = new Texture(albumCoverFromBytes);
albumCoverFromBytes.dispose();
} else {
this.albumCover = defaultAlbumCover;
}
}
public long getDurationInSeconds() {
return durationInSeconds;
}
public String getSongName() {
return songName.replace('_', ' ');
}
public Texture getAlbumCover() {
return albumCover;
}
public String getAuthor() {
return author;
}
public int getPreviousTop() {
return previousTop;
}
public int getRatedDifficulty() {
return ratedDifficulty;
}
public boolean isInvalidMusic() {
return invalidMusic;
}
@Override
public void dispose() {
albumCover.dispose();
}
}

View File

@@ -0,0 +1,161 @@
package zero1hd.rhythmbullet.audio;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.audio.mp3.MP3File;
import org.jaudiotagger.tag.TagException;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.files.FileHandle;
import javazoom.jl.decoder.Decoder;
public class Mp3AudioData implements AudioData {
private int readWindowSize = 1024;
private AudioInputStream din;
private AudioFormat decodedFormat;
private Music playbackMusic;
private int readIndex;
private int sampleCount;
private float durationInSeconds;
private AudioInputStream in;
Decoder decoder = new Decoder();
public Mp3AudioData(FileHandle audioFile) {
try {
MP3File mp3File = new MP3File(audioFile.file());
sampleCount = (int) mp3File.getMP3AudioHeader().getNumberOfFrames();
durationInSeconds = mp3File.getMP3AudioHeader().getNumberOfFrames()/readWindowSize;
} catch (IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e1) {
e1.printStackTrace();
}
reset();
try {
File file = audioFile.file();
in = AudioSystem.getAudioInputStream(file);
din = null;
AudioFormat baseFormat = in.getFormat();
decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16,
baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);
din = AudioSystem.getAudioInputStream(decodedFormat, in);
} catch (UnsupportedAudioFileException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
playbackMusic = Gdx.audio.newMusic(audioFile);
}
@Override
public void readIndexUpdate() {
readIndex = (int) (playbackMusic.getPosition() * decodedFormat.getSampleRate() / readWindowSize);
}
@Override
public int getReadIndex() {
return readIndex;
}
@Override
public void reset() {
if (playbackMusic != null) {
playbackMusic.stop();
}
}
@Override
public int getReadWindowSize() {
return readWindowSize;
}
@Override
public Music getPlaybackMusic() {
return playbackMusic;
}
byte[] toBeConverted = new byte[2];
@Override
public int readSamples(float[] samples) {
int samplesRead = 0;
short sampleAverage = 0;
for (int currentSample = 0; currentSample < samples.length; currentSample++) {
for (int channel = 0; channel < decodedFormat.getChannels(); channel++) {
try {
int readCount = din.read(toBeConverted, 0, toBeConverted.length);
ByteBuffer bBuffer = ByteBuffer.allocate(2);
bBuffer.order(ByteOrder.LITTLE_ENDIAN);
bBuffer.put(toBeConverted[0]);
bBuffer.put(toBeConverted[1]);
sampleAverage += bBuffer.getShort(0);
if (readCount == -1) {
break;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
sampleAverage /= decodedFormat.getChannels() * Short.MAX_VALUE + 1;
samples[currentSample] = sampleAverage;
sampleAverage = 0;
samplesRead++;
}
return samplesRead;
}
@Override
public AudioFormat getFormat() {
return decodedFormat;
}
@Override
public int getSampleCount() {
return sampleCount;
}
@Override
public void dispose() {
reset();
playbackMusic.dispose();
if (din != null) {
try {
din.close();
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public float getDuration() {
return durationInSeconds;
}
}

View File

@@ -0,0 +1,88 @@
package zero1hd.rhythmbullet.audio;
import java.io.IOException;
import java.security.InvalidParameterException;
import javax.sound.sampled.AudioFormat;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.files.FileHandle;
import zero1hd.wavedecoder.WavDecoder;
public class WavAudioData implements AudioData {
private int readWindowSize = 1024;
private AudioFormat format;
int readIndex;
Music playbackMusic;
WavDecoder decoder;
public WavAudioData(FileHandle file) {
reset();
try {
decoder = new WavDecoder(file);
decoder.initDataStream();
decoder.getHeaderInfo();
} catch (InvalidParameterException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
playbackMusic = Gdx.audio.newMusic(file);
format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, (float) decoder.getSampleRate(), 16, decoder.getChannels(), decoder.getChannels()*2, (float) decoder.getSampleRate(), false);
}
@Override
public void readIndexUpdate() {
readIndex = (int) (playbackMusic.getPosition() * decoder.getSampleRate() / readWindowSize);
}
@Override
public int getReadIndex() {
return readIndex;
}
@Override
public void reset() {
if (playbackMusic != null) {
playbackMusic.stop();
}
}
@Override
public int getReadWindowSize() {
return readWindowSize;
}
@Override
public Music getPlaybackMusic() {
return playbackMusic;
}
@Override
public int readSamples(float[] samples) {
return decoder.readSamples(samples);
}
@Override
public AudioFormat getFormat() {
return format;
}
@Override
public int getSampleCount() {
return decoder.getDataSize()/(2*decoder.getChannels());
}
@Override
public void dispose() {
reset();
playbackMusic.dispose();
decoder.cleanAndClose();
}
@Override
public float getDuration() {
return decoder.getDurationInSeconds();
}
}

View File

@@ -0,0 +1,25 @@
package zero1hd.rhythmbullet.audio.map;
import java.util.HashMap;
import zero1hd.rhythmbullet.entity.EntityIndex;
public class EntitySpawnInfo {
private EntityIndex entityType;
// private float[] parameters;
public HashMap<String, Float> parameters;
public EntitySpawnInfo(EntityIndex entityType) {
this.entityType = entityType;
parameters = new HashMap<>();
}
public EntityIndex getEntityType() {
return entityType;
}
@Override
public String toString() {
return entityType.name() + ": " + parameters.size();
}
}

View File

@@ -0,0 +1,93 @@
package zero1hd.rhythmbullet.audio.map;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.entity.EntityIndex;
public class GamePlayMap {
private AudioData musicData;
private MapWindowData[] spawnList;
private boolean building;
private int index;
/**
* GamePlayMap is what the game area will use to generate entities and judge current audio data
* @param audioData audio data
*/
public GamePlayMap(AudioData audioData, int totalWindows) {
this.musicData = audioData;
spawnList = new MapWindowData[totalWindows];
}
public int setIndex(int index) {
int previousIndex = this.index;
if (index < 0) {
this.index = 0;
} else if (index >= spawnList.length) {
toHead();
} else {
this.index = index;
}
return previousIndex;
}
public EntitySpawnInfo addEntity(EntityIndex entityType) {
if (building) {
if (spawnList[index] == null) {
spawnList[index] = new MapWindowData();
}
EntitySpawnInfo esi = new EntitySpawnInfo(entityType);
spawnList[index].addEntity(esi);
return esi;
} else {
throw new IllegalStateException("Stupid, you need to call begin building first first.");
}
}
public void nextWindowData() {
if (building) {
index++;
} else {
throw new IllegalStateException("Stupid, you need to call begin building first first.");
}
}
public void toHead() {
index = spawnList.length-1;
}
public AudioData getMusicData() {
return musicData;
}
public void beginBuild() {
if (!building) {
index = 0;
building = true;
} else {
throw new IllegalStateException("Excuse me, but your already building...");
}
}
public void endBuild() {
if (building) {
index = 0;
building = false;
} else {
throw new IllegalStateException("Nothings being built...");
}
}
public MapWindowData getCurrentWindowBasedOnIndex() {
if (index != musicData.getReadIndex()) {
index = musicData.getReadIndex();
if (index < spawnList.length) {
return spawnList[index];
}
}
return null;
}
public int getIndex() {
return index;
}
}

View File

@@ -0,0 +1,19 @@
package zero1hd.rhythmbullet.audio.map;
import com.badlogic.gdx.utils.Array;
public class MapWindowData {
Array<EntitySpawnInfo> entityDatas;
public MapWindowData() {
entityDatas = new Array<>(EntitySpawnInfo.class);
}
public void addEntity(EntitySpawnInfo entity) {
entityDatas.add(entity);
}
public EntitySpawnInfo[] getArray() {
return entityDatas.toArray();
}
}

View File

@@ -0,0 +1,133 @@
package zero1hd.rhythmbullet.audio.map;
import org.apache.commons.math3.random.MersenneTwister;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.FloatArray;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.entity.EntityIndex;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniSender;
public class RhythmMapAlgorithm implements Runnable {
private MiniSender sender;
private FloatArray bassPeaks;
private FloatArray mPeaks;
private FloatArray umPeaks;
private MersenneTwister rand;
private GamePlayMap map;
private float avgBass;
private float avgUM;
private float avgSPB;
private float umMax, bassMax;
private float speedMod, healthMod, difficultyMod;
private float windowPerSecond;
private volatile int progress;
public RhythmMapAlgorithm(AudioAnalyzer analyzer, float speedMod, float healthMod, float difficultyMod) {
sender = new MiniSender();
bassPeaks = analyzer.getBassPeaks();
mPeaks = analyzer.getmPeaks();
umPeaks = analyzer.getUMPeaks();
map = new GamePlayMap(analyzer.getAudioData(), umPeaks.size);
rand = new MersenneTwister(analyzer.getPUID());
avgSPB = analyzer.getAvgSPB();
windowPerSecond = 1/analyzer.getsecondsPerWindow();
this.speedMod = speedMod;
this.healthMod = healthMod;
this.difficultyMod = difficultyMod;
umMax = analyzer.getUMMaxValue();
avgUM = analyzer.getUmAvg();
bassMax = analyzer.getBassMaxValue();
avgBass = analyzer.getBassAvg();
}
EntitySpawnInfo esi;
@Override
public void run() {
map.beginBuild();
for (int index = 0; index < bassPeaks.size; index++) {
if (bassPeaks.get(index) != 0 || umPeaks.get(index) != 0) {
if (bassPeaks.get(index) != 0) {
//If there is a value of some sorts that is not zero, we generate some beat for the map
if (index > 1.5*windowPerSecond && bassPeaks.get(index) > avgBass) {
//If bass peak is greater than the bass peak average, then:
int normalIndexPos = map.setIndex((int) (map.getIndex() - windowPerSecond*1.5f));
float waitTime = 1.5f;
float endRadius = (bassPeaks.get(index)/bassMax)*(Main.GAME_AREA_HEIGHT/4f);
esi = map.addEntity(EntityIndex.VOID_CIRCLE);
esi.parameters.put("warningTime", waitTime);
esi.parameters.put("endRadius", endRadius);
esi.parameters.put("growthRate", endRadius/(avgSPB*0.8f));
esi.parameters.put("x", rand.nextFloat()*Main.GAME_AREA_WIDTH);
esi.parameters.put("y", rand.nextFloat()*Main.GAME_AREA_HEIGHT);
map.setIndex(normalIndexPos);
} else {
}
}
if (umPeaks.get(index) != 0) {
if (umPeaks.get(index) >= avgUM) {
//If upper midrange peaks are greater than average, the:
int spawnLocations = (Main.GAME_AREA_WIDTH-8)/8;
esi = map.addEntity(EntityIndex.BAR);
esi.parameters.put("x", (float) (MathUtils.round(rand.nextFloat()*spawnLocations)*8));
esi.parameters.put("rate", (8f/avgSPB)*speedMod);
} else {
float xSpawnLocation = (rand.nextFloat()*(Main.GAME_AREA_WIDTH-2))+1;
esi = map.addEntity(EntityIndex.PELLET);
esi.parameters.put("x", xSpawnLocation);
esi.parameters.put("y", Main.GAME_AREA_HEIGHT-0.25f);
esi.parameters.put("angle", 140*rand.nextFloat()+200f);
esi.parameters.put("speed", (Main.GAME_AREA_HEIGHT/4f)/avgSPB);
}
}
if (rand.nextFloat() < 0.15f) {
switch(rand.nextInt(10)) {
case 0:
break;
}
}
}
map.nextWindowData();
progress = MathUtils.round(100f*index/bassPeaks.size);
sender.send(MiniEvents.MAPGEN_ITERATED);
}
map.endBuild();
sender.send(MiniEvents.MAP_GENERATED);
}
public synchronized GamePlayMap getMap() {
return map;
}
public synchronized int getProgress() {
return progress;
}
public MiniSender getSender() {
return sender;
}
}

View File

@@ -0,0 +1,150 @@
package zero1hd.rhythmbullet.controls;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import zero1hd.rhythmbullet.Main;
public class KeyMap {
TextureAtlas keyTextures;
private Preferences keyBindPrefs;
public static final String UP = "up";
public static final String DOWN = "down";
public static final String LEFT = "left";
public static final String RIGHT = "right";
public static final String SHOOT = "shoot";
public static final String FIRSTTHIRDTELEPORT = "firstThirdTP";
public static final String SECONDTHIRDTELEPORT = "secondThirdTP";
public static final String THIRDTHIRDTELEPORT = "thirdThirdTP";
public static final String ACCELERATE = "accelerate";
/**
* forward binding.
*/
public static int up;
/**
* backward binding.
*/
public static int down;
/**
* left binding.
*/
public static int left;
/**
* right binding.
*/
public static int right;
/**
* shoot binding
*/
public static int shoot;
/**
* teleport first third binding
*/
public static int firstThirdTeleport;
/**
* teleport second third binding
*/
public static int secondThirdTeleport;
/**
* teleport third third binding
*/
public static int thirdThirdTeleport;
public static int accelerate;
public KeyMap(Main core) {
keyTextures = core.getAssetManager().get("keyboard.atlas", TextureAtlas.class);
setKeys(Gdx.app.getPreferences("PolyJet_Controls"));
updateKeys();
}
public Preferences getKeys() {
return keyBindPrefs;
}
public void setKeys(Preferences keys) {
this.keyBindPrefs = keys;
}
public TextureRegion getIcon(int keycode) {
// Gdx.app.debug("Keycode texture name", Keys.toString(keycode));
switch (keycode) {
case Keys.ALT_LEFT:
case Keys.ALT_RIGHT:
return keyTextures.findRegion("Keyboard_Black_Alt");
case Keys.SHIFT_LEFT:
case Keys.SHIFT_RIGHT:
return keyTextures.findRegion("Keyboard_Black_Shift");
case Keys.LEFT_BRACKET:
return keyTextures.findRegion("Keyboard_Black_Bracket_Left");
case Keys.RIGHT_BRACKET:
return keyTextures.findRegion("Keyboard_Black_Bracket_Right");
case Keys.SEMICOLON:
return keyTextures.findRegion("Keyboard_Black_Semicolon");
case Keys.SLASH:
return keyTextures.findRegion("Keyboard_Black_Slash");
case Keys.NUM:
return keyTextures.findRegion("Keyboard_Black_Num_Lock");
default:
return keyTextures.findRegion("Keyboard_Black_" + Keys.toString(keycode).replace(' ', '_'));
}
}
public void updateKeys() {
up = keyBindPrefs.getInteger(KeyMap.UP, Keys.UP);
down = keyBindPrefs.getInteger(KeyMap.DOWN, Keys.DOWN);
left = keyBindPrefs.getInteger(KeyMap.LEFT, Keys.LEFT);
right = keyBindPrefs.getInteger(KeyMap.RIGHT, Keys.RIGHT);
shoot = keyBindPrefs.getInteger(KeyMap.SHOOT, Keys.SPACE);
firstThirdTeleport = keyBindPrefs.getInteger(KeyMap.FIRSTTHIRDTELEPORT, Keys.Q);
secondThirdTeleport = keyBindPrefs.getInteger(KeyMap.SECONDTHIRDTELEPORT, Keys.W);
thirdThirdTeleport = keyBindPrefs.getInteger(KeyMap.THIRDTHIRDTELEPORT, Keys.E);
accelerate = keyBindPrefs.getInteger(KeyMap.ACCELERATE, Keys.SHIFT_LEFT);
}
/**
* resets all binding to default;
*/
public void resetAllBinding() {
keyBindPrefs.clear();
keyBindPrefs.flush();
}
public int stringToID(String control) {
if (control == KeyMap.UP) {
return KeyMap.up;
} else if (control == KeyMap.DOWN) {
return KeyMap.down;
} else if (control == KeyMap.LEFT) {
return KeyMap.left;
} else if (control == KeyMap.RIGHT) {
return KeyMap.right;
} else if (control == KeyMap.SHOOT) {
return KeyMap.shoot;
} else if (control == KeyMap.FIRSTTHIRDTELEPORT) {
return KeyMap.firstThirdTeleport;
} else if (control == KeyMap.SECONDTHIRDTELEPORT) {
return KeyMap.secondThirdTeleport;
} else if (control == KeyMap.THIRDTHIRDTELEPORT) {
return KeyMap.thirdThirdTeleport;
} else if (control == KeyMap.ACCELERATE) {
return KeyMap.accelerate;
} else {
return -1;
}
}
}

View File

@@ -0,0 +1,91 @@
package zero1hd.rhythmbullet.entity;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.graphics.g2d.ParticleEffectPool;
import com.badlogic.gdx.graphics.g2d.ParticleEffectPool.PooledEffect;
import com.badlogic.gdx.utils.Array;
import zero1hd.rhythmbullet.Main;
public class CollisionDetector {
Array<Entity> enemies;
Array<Entity> allies;
AssetManager assets;
Preferences prefs;
//Particle pools;
ParticleEffectPool explosionEffectPool;
Array<PooledEffect> effects = new Array<>();
Sound explosionSFX;
public CollisionDetector(Array<Entity> enemies, Array<Entity> allies, AssetManager assetManager, Preferences prefs) {
this.enemies = enemies;
this.allies = allies;
assets = assetManager;
this.prefs = prefs;
explosionEffectPool = new ParticleEffectPool(assets.get("explosion-s.p", ParticleEffect.class), 1, 64);
explosionSFX = assets.get("explosion.ogg", Sound.class);
}
public void collisionCheck() {
if ((enemies.size != 0) && (allies.size != 0)) {
for (int f = 0; f < enemies.size; f++) {
Entity enemy = enemies.get(f);
if (enemy.getHitZone() != null) {
for (int s = 0; s < allies.size; s++) {
Entity ally = allies.get(s);
if (ally.getHitZone() != null) {
if (enemy.getHitZone().overlaps(ally.getHitZone())) {
Gdx.app.debug("Collision Detector", "Collision between entities: " + enemy.getEntityType() + " and " + ally.getEntityType());
//Play FX;
if (ally.playCollideSFX() && enemy.playCollideSFX()) {
explosionSFX.play(prefs.getFloat("fx vol")/100f, 1f, (enemy.getX()/Main.GAME_AREA_WIDTH));
}
if (ally.playCollidePFX() && enemy.playCollidePFX()) {
PooledEffect currentPFX;
currentPFX = explosionEffectPool.obtain();
currentPFX.setPosition(ally.getX() + ally.getWidth()/2f, ally.getY() + ally.getHeight()/2f);
effects.add(currentPFX);
}
enemy.collided(ally);
ally.collided(enemy);
break;
}
}
}
}
}
}
}
/**
* draws the explosion particles where necessecary.
* @param batch the batch used to draw the said particles
* @param cleanBatch whether this method should call begin and end on the batch.
*/
public void renderParticles(Batch batch, float delta, boolean cleanBatch) {
if (cleanBatch) {
batch.begin();
}
for (int i = 0; i < effects.size; i++) {
effects.get(i).draw(batch, delta);
if (effects.get(i).isComplete()) {
effects.get(i).free();
effects.removeIndex(i);
}
}
if (cleanBatch) {
batch.end();
}
}
}

View File

@@ -0,0 +1,183 @@
package zero1hd.rhythmbullet.entity;
import java.util.HashMap;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.utils.Pool.Poolable;
public class Entity extends Actor implements Poolable {
private EntityFrame<?> ef;
protected AssetManager assets;
protected Preferences prefs;
protected EntityController ec;
protected boolean enemy;
protected boolean simple = true;
protected boolean nonStnrd = false;
protected boolean move = true;
protected Rectangle hitbox;
protected Sprite sprite;
protected Vector2 rotRatios;
protected Vector2 center;
protected float angle;
protected float speed;
/**
* called by the entity frame and only once (when this object is created).
*/
protected void setup(EntityController ec, EntityFrame<?> ef) {
this.ec = ec;
this.ef = ef;
assets = ec.getAssets();
prefs = ec.getPrefs();
rotRatios = new Vector2();
center = new Vector2();
hitbox = new Rectangle();
preInit();
}
public void preInit() {
if (sprite.getTexture() == null) throw new NullPointerException("what, your not going to have a texture for your entity?");
sprite.setOriginCenter();
}
public void init(HashMap<String, Float> params) {
}
/**
* Called whenever a collision is detected
* @param entity is the entity that hit this one.
*/
public void collided(Entity entity) {
}
/**
* gets the box that represents the hit box to calculate whether there is a collision or not
* @return the object that represents the hit box
*/
public Rectangle getHitZone() {
return hitbox;
}
/**
* gets the type of entity this entity is
* @return the entity type
*/
public EntityIndex getEntityType() {
return null;
}
/**
* If this entity's life span is over, it should be considered dead. Useful for knowing what can be freed in a pool scenario.
* @return if this entity is dead or not.
*/
public boolean isDead() {
return false;
}
@Override
public void act(float delta) {
if (!nonStnrd) {
if (move) {
move(delta, false);
}
if (simple) {
sprite.setPosition(getX(), getY());
hitbox.setPosition(getX(), getY());
sprite.setSize(getWidth(), getHeight());
hitbox.setSize(getWidth(), getHeight());
} else {
sprite.setCenter(center.x, center.y);
hitbox.setCenter(center);
sprite.setOriginCenter();
sprite.setRotation(angle);
}
super.act(delta);
if (isDead()) {
ef.recycleEntity(this);
}
}
}
@Override
public void draw(Batch batch, float parentAlpha) {
if (!nonStnrd) {
sprite.draw(batch);
}
batch.setColor(Color.WHITE);
super.draw(batch, parentAlpha);
}
public boolean playCollidePFX() {
return true;
}
public boolean playCollideSFX() {
return true;
}
public void move(float delta, boolean update) {
rotRatios.set(MathUtils.cosDeg(angle), MathUtils.sinDeg(angle));
moveBy(rotRatios.x*speed*delta, rotRatios.y*speed*delta);
center.set(getX() + getWidth()/2f, getY() + getHeight()/2f);
if (update) {
updatePositionData();
}
}
public void updatePositionData() {
if (simple) {
sprite.setPosition(getX(), getY());
hitbox.setPosition(getX(), getY());
} else {
sprite.setCenter(center.x, center.y);
hitbox.setCenter(center);
sprite.setRotation(angle);
}
}
@Override
public void reset() {
rotRatios.set(0, 0);
hitbox.set(0, 0, 0, 0);
sprite.setPosition(0, 0);
sprite.setRotation(0);
setPosition(0, 0);
center.set(0, 0);
angle = 0;
speed = 0;
}
public Vector2 getCenter() {
return center;
}
public float getAngle() {
return angle;
}
public void setSpeed(float speed) {
this.speed = speed;
}
public float getSpeed() {
return speed;
}
}

View File

@@ -0,0 +1,71 @@
package zero1hd.rhythmbullet.entity;
import java.util.HashMap;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.Array;
import zero1hd.rhythmbullet.entity.ally.Laser;
import zero1hd.rhythmbullet.entity.enemies.Bar;
import zero1hd.rhythmbullet.entity.enemies.Flake;
import zero1hd.rhythmbullet.entity.enemies.Pellet;
import zero1hd.rhythmbullet.entity.enemies.Shard;
import zero1hd.rhythmbullet.entity.enemies.VoidCircle;
public class EntityController {
private AssetManager assets;
private Preferences prefs;
private Stage stage;
public Array<Entity> activeAllies;
public Array<Entity> activeEnemies;
public EntityFrame<VoidCircle> voidCircle;
public EntityFrame<Pellet> pellet;
public EntityFrame<Shard> shard;
public EntityFrame<Bar> bar;
public EntityFrame<Flake> flake;
public EntityFrame<Laser> laser;
private HashMap<EntityIndex, EntityFrame<? extends Entity>> index = new HashMap<>();
public EntityController(AssetManager assetManager, Preferences preferences, Stage stage) {
activeAllies = new Array<Entity>();
activeEnemies = new Array<Entity>();
this.assets = assetManager;
this.prefs = preferences;
this.stage = stage;
setup();
}
private void setup() {
index.put(EntityIndex.VOID_CIRCLE, (voidCircle = new EntityFrame<>(this, VoidCircle.class)));
index.put(EntityIndex.PELLET, pellet = new EntityFrame<>(this, Pellet.class));
index.put(EntityIndex.SHARD, shard = new EntityFrame<>(this, Shard.class));
index.put(EntityIndex.BAR, bar = new EntityFrame<>(this, Bar.class));
index.put(EntityIndex.FLAKE, flake = new EntityFrame<>(this, Flake.class));
index.put(EntityIndex.LASER, laser = new EntityFrame<>(this, Laser.class));
}
public HashMap<EntityIndex, EntityFrame<? extends Entity>> getIndex() {
return index;
}
public Stage getStage() {
return stage;
}
public AssetManager getAssets() {
return assets;
}
public Preferences getPrefs() {
return prefs;
}
}

View File

@@ -0,0 +1,56 @@
package zero1hd.rhythmbullet.entity;
import com.badlogic.gdx.utils.Pool;
public class EntityFrame<T extends Entity> {
private Pool<T> pool;
private EntityController ec;
Class<T> ct;
EntityFrame<T> ef;
public EntityFrame(EntityController entityController, Class<T> classType) {
ct = classType;
ef = this;
ec = entityController;
pool = new Pool<T>() {
@Override
protected T newObject() {
try {
T entity = ct.newInstance();
entity.setup(ec, ef);
return entity;
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
};
}
public T buildEntity() {
T entity = pool.obtain();
if (entity.enemy) {
ec.activeEnemies.add(entity);
} else {
ec.activeAllies.add(entity);
}
return entity;
}
/**
* Free the entity if no longer used.
* @param entity to be freed.
*/
public void recycleEntity(Entity entity) {
if (entity.enemy) {
ec.activeEnemies.removeValue(entity, true);
} else {
ec.activeAllies.removeValue(entity, true);
}
entity.remove();
pool.free(ct.cast(entity));
}
}

View File

@@ -0,0 +1,24 @@
package zero1hd.rhythmbullet.entity;
import zero1hd.rhythmbullet.entity.ally.Laser;
import zero1hd.rhythmbullet.entity.ally.PolyJetEntity;
import zero1hd.rhythmbullet.entity.enemies.Bar;
import zero1hd.rhythmbullet.entity.enemies.Flake;
import zero1hd.rhythmbullet.entity.enemies.Pellet;
import zero1hd.rhythmbullet.entity.enemies.Shard;
import zero1hd.rhythmbullet.entity.enemies.VoidCircle;
public enum EntityIndex {
POLYJET(PolyJetEntity.class), BAR(Bar.class), VOID_CIRCLE(VoidCircle.class), SHARD(Shard.class), LASER(Laser.class), PELLET(Pellet.class), FLAKE(Flake.class);
private final Class<? extends Entity> classType;
private EntityIndex(Class<? extends Entity> classType) {
this.classType = classType;
}
public Class<? extends Entity> getClassType() {
return classType;
}
}

View File

@@ -0,0 +1,86 @@
package zero1hd.rhythmbullet.entity.ally;
import java.util.HashMap;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.entity.Entity;
import zero1hd.rhythmbullet.entity.EntityIndex;
public class Laser extends Entity {
boolean dead;
Sound sfx;
@Override
public void preInit() {
sprite = new Sprite(assets.get("laser.png", Texture.class));
sfx = assets.get("laser.ogg", Sound.class);
setSize(0.25f, 2f);
super.preInit();
}
public void init(float x, float y, float rate) {
setPosition(x-getWidth()/2f, y-getHeight()/2f);
speed = rate;
sfx.play(prefs.getFloat("fx vol")/100f);
toBack();
angle = 90f;
}
/**
* Vars: x, y, rate;
*/
@Override
public void init(HashMap<String, Float> params) {
setX(params.get("x") - getWidth()/2f);
setY(params.get("y") - getHeight()/2f);
speed = params.get("rate");
angle = 90f;
sfx.play(prefs.getFloat("fx vol")/100f);
super.init(params);
}
@Override
public void act(float delta) {
toBack();
if (getY() > Main.GAME_AREA_HEIGHT) {
dead = true;
}
super.act(delta);
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
}
@Override
public void reset() {
dead = false;
super.reset();
}
@Override
public void collided(Entity entity) {
switch (entity.getEntityType()) {
default:
dead = true;
break;
}
}
@Override
public EntityIndex getEntityType() {
return EntityIndex.LASER;
}
@Override
public boolean isDead() {
return dead;
}
}

View File

@@ -0,0 +1,103 @@
package zero1hd.rhythmbullet.entity.ally;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.entity.Entity;
import zero1hd.rhythmbullet.entity.EntityIndex;
public class PolyJetEntity extends Entity {
public float health;
private ParticleEffect thrust;
private Texture polyjet;
private ParticleEffect teleportCloak;
public boolean moveLeft, moveRight, moveUp, moveDown, teleporting, accelerate;
private float speed, accel;
private float rate;
public PolyJetEntity(AssetManager assets, float speed, float accel, String jet) {
nonStnrd = true;
health = 100;
this.speed = speed;
this.accel = accel;
setSize(1.5f, 1.5f);
setPosition(Main.GAME_AREA_WIDTH/2 - getWidth()/2, -4f);
hitbox = new Rectangle(getX(), getY(), getWidth(), getHeight());
polyjet = assets.get("polyjet-" + jet + ".png", Texture.class);
thrust = assets.get("standard_thrust.p", ParticleEffect.class);
thrust.start();
teleportCloak = assets.get("teleport-cloak.p", ParticleEffect.class);
addAction(Actions.moveTo(getX(), 4f, 0.5f));
}
@Override
public void act(float delta) {
hitbox.setPosition(getX(), getY());
thrust.setPosition(getX()+(getWidth())/2 - 1f/16f, getY()-0.2f);
thrust.update(delta);
teleportCloak.setPosition(getX() +(getWidth()-1)/2, getY() + (getHeight()-1)/2);
//Movement!
if (accelerate) {
rate = speed + accel;
} else {
rate = speed;
}
if (moveLeft && !moveRight) {
moveBy(-(rate*delta), 0);
}
if (moveRight && !moveLeft) {
moveBy(rate*delta, 0);
}
if (moveUp && !moveDown) {
moveBy(0, rate*delta);
}
if (moveDown && !moveUp) {
moveBy(0, -rate*delta);
}
super.act(delta);
}
@Override
public void draw(Batch batch, float parentAlpha) {
thrust.draw(batch);
batch.draw(polyjet, getX(), getY(), getWidth(), getHeight());
super.draw(batch, parentAlpha);
}
@Override
public EntityIndex getEntityType() {
return EntityIndex.POLYJET;
}
@Override
public void collided(Entity entity) {
}
@Override
public boolean isDead() {
if (health <= 0) {
return true;
} else {
return false;
}
}
public Rectangle getHitbox() {
return hitbox;
}
}

View File

@@ -0,0 +1,79 @@
package zero1hd.rhythmbullet.entity.enemies;
import java.util.HashMap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.Rectangle;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.entity.Entity;
import zero1hd.rhythmbullet.entity.EntityIndex;
public class Bar extends Entity {
private boolean dead;
@Override
public void preInit() {
setSize(8f, 0.5f);
sprite = new Sprite(assets.get("bar.png", Texture.class));
enemy = true;
super.preInit();
}
public void init(float x, float rate) {
setPosition(x, Main.GAME_AREA_HEIGHT);
speed = rate;
angle = 270;
}
@Override
public void init(HashMap<String, Float> params) {
setPosition(params.get("x"), Main.GAME_AREA_HEIGHT);
speed = params.get("rate");
angle = 270;
super.init(params);
}
@Override
public void act(float delta) {
hitbox.setPosition(getX(), getY());
super.act(delta);
if (getY() < 0-getHeight()) {
dead = true;
}
}
@Override
public void reset() {
dead = false;
super.reset();
}
@Override
public void collided(Entity entity) {
switch (entity.getEntityType()) {
case POLYJET:
dead = true;
break;
default:
break;
}
}
@Override
public Rectangle getHitZone() {
return hitbox;
}
@Override
public EntityIndex getEntityType() {
return EntityIndex.BAR;
}
@Override
public boolean isDead() {
return dead;
}
}

View File

@@ -0,0 +1,136 @@
package zero1hd.rhythmbullet.entity.enemies;
import java.util.HashMap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.Rectangle;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.entity.Entity;
import zero1hd.rhythmbullet.entity.EntityIndex;
public class Flake extends Entity {
private float timer;
private float totalTime;
private Shard[] shards;
@Override
public void preInit() {
sprite = new Sprite(assets.get("flake.png", Texture.class));
simple = true;
enemy = true;
move = false;
setSize(3f, 3f);
super.preInit();
}
public void init(float x, float y, float rate, float fuse, float angle, int shardCount) {
this.shards = new Shard[shardCount];
for (int i = 0; i < shards.length; i++) {
shards[i] = ec.shard.buildEntity();
shards[i].init(x, y, 360/shards.length*i, 0, 2);
ec.getStage().addActor(shards[i]);
}
this.speed = rate;
this.timer = fuse;
this.totalTime = fuse;
this.angle = angle;
hitbox.setSize(getWidth(), getHeight());
setPosition(x-getWidth()/2f, y-getHeight()/2f);
}
/**
* params: shardCount, x, y, rate, fuse, angle;
*/
@Override
public void init(HashMap<String, Float> params) {
this.shards = new Shard[params.get("shardCount").intValue()];
for (int i = 0; i < shards.length; i++) {
shards[i] = ec.shard.buildEntity();
shards[i].init(params.get("x"), params.get("y"), 360/shards.length*i, 0, 2);
ec.getStage().addActor(shards[i]);
}
this.speed = params.get("rate");
this.timer = params.get("fuse");
this.totalTime = timer;
this.angle = params.get("angle");
hitbox.setSize(getWidth(), getHeight());
setPosition(params.get("x")-getWidth()/2f, params.get("y")-getHeight()/2f);
super.init(params);
}
@Override
public void act(float delta) {
if (timer > 0) {
timer -= delta;
}
move(delta, false);
System.out.println("---Start----");
System.out.println("Flake: " + center);
for (int i = 0; i < shards.length; i++) {
shards[i].setPosition(center.x-shards[i].getWidth()/2f, center.y-shards[i].getWidth()/2f);
shards[i].move(delta, true);
System.out.println("Shard " + i + ": " + shards[i].getCenter());
System.out.println("Sprite Pos: " + shards[i].getHitZone());
}
if (getX() > Main.GAME_AREA_WIDTH || getY() > Main.GAME_AREA_HEIGHT || getX() < 0-getWidth() || getY() < 0-getHeight()) {
timer = 0;
}
super.act(delta);
}
@Override
public void draw(Batch batch, float parentAlpha) {
sprite.setColor(0.1f,0.1f,0.1f, timer/totalTime);
super.draw(batch, parentAlpha);
}
@Override
public void collided(Entity entity) {
switch (entity.getEntityType()) {
case LASER:
timer --;
break;
default:
break;
}
}
@Override
public Rectangle getHitZone() {
return hitbox;
}
@Override
public EntityIndex getEntityType() {
return EntityIndex.FLAKE;
}
@Override
public boolean isDead() {
if (timer <= 0) {
for (int i = 0; i < shards.length; i++) {
shards[i].setSpeed(45f);
}
return true;
} else {
return false;
}
}
@Override
public void reset() {
timer = 0;
shards = null;
hitbox.set(0, 0, 0, 0);
totalTime = 0;
super.reset();
}
}

View File

@@ -0,0 +1,78 @@
package zero1hd.rhythmbullet.entity.enemies;
import java.util.HashMap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.utils.Pool.Poolable;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.entity.Entity;
import zero1hd.rhythmbullet.entity.EntityIndex;
public class Pellet extends Entity implements Poolable {
private boolean dead;
@Override
public void preInit() {
sprite = new Sprite(assets.get("pellet.png", Texture.class));
enemy = true;
setSize(0.5f, 0.5f);
super.preInit();
}
public void init(float x, float y, float angle, float rate) {
setPosition(x, y);
this.speed = rate;
this.angle = angle;
}
/**
* Vars: x, y, speed, angle;
*/
@Override
public void init(HashMap<String, Float> params) {
setPosition(params.get("x"), params.get("y"));
speed = params.get("speed");
angle = params.get("angle");
super.init(params);
}
@Override
public void act(float delta) {
super.act(delta);
if (getX() > Main.GAME_AREA_WIDTH || getY() > Main.GAME_AREA_HEIGHT || getX() < 0-getWidth() || getY() < 0-getHeight()) {
dead = true;
}
}
@Override
public void collided(Entity entity) {
switch (entity.getEntityType()) {
default:
dead = true;
break;
}
super.collided(entity);
}
@Override
public EntityIndex getEntityType() {
return EntityIndex.PELLET;
}
@Override
public boolean isDead() {
return dead;
}
@Override
public void reset() {
dead = false;
super.reset();
}
}

View File

@@ -0,0 +1,99 @@
package zero1hd.rhythmbullet.entity.enemies;
import java.util.HashMap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.Rectangle;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.entity.Entity;
import zero1hd.rhythmbullet.entity.EntityIndex;
public class Shard extends Entity {
private int hp;
private int maxHp;
@Override
public void preInit() {
sprite = new Sprite(assets.get("shard.png", Texture.class));
setSize(2f, 2f);
sprite.setSize(3f, 2f);
simple = false;
enemy = true;
super.preInit();
}
public void init(float x, float y, float angle, float rate, int hp) {
speed = rate;
this.hp = hp;
maxHp = hp;
this.angle = angle;
setPosition(x-(getWidth()/2f), y-(getHeight()/2f));
hitbox.setSize(getWidth(), getHeight());
}
/**
* x, y, angle, rate, hp;
*/
@Override
public void init(HashMap<String, Float> params) {
setX(params.get("x"));
setY(params.get("y"));
angle = params.get("angle");
speed = params.get("rate");
hp = params.get("hp").intValue();
super.init(params);
}
@Override
public void reset() {
hp = 0;
maxHp = 0;
}
@Override
public void act(float delta) {
if (getX() > Main.GAME_AREA_WIDTH || getY() > Main.GAME_AREA_HEIGHT || getX() < 0-getWidth() || getY() < 0-getHeight()) {
hp = 0;
}
super.act(delta);
}
@Override
public void draw(Batch batch, float parentAlpha) {
sprite.setColor(((float)hp/(float)maxHp), ((float)hp/(float)maxHp), ((float)hp/(float)maxHp), 0.5f);
super.draw(batch, parentAlpha);
}
@Override
public void collided(Entity entity) {
switch (entity.getEntityType()) {
case LASER:
hp--;
break;
default:
break;
}
}
@Override
public Rectangle getHitZone() {
return hitbox;
}
@Override
public EntityIndex getEntityType() {
return EntityIndex.SHARD;
}
@Override
public boolean isDead() {
if (hp <= 0) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,135 @@
package zero1hd.rhythmbullet.entity.enemies;
import java.util.HashMap;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import zero1hd.rhythmbullet.entity.Entity;
import zero1hd.rhythmbullet.entity.EntityIndex;
public class VoidCircle extends Entity {
private float timer;
private float endRadius;
private float currentRadius;
private float growthRate;
private boolean done;
private boolean begin;
private float maxTime;
private Sound sound;
@Override
public void preInit() {
sprite = new Sprite(assets.get("void_circle.png", Texture.class));
simple = false;
enemy = true;
sound = assets.get("disintegrate.ogg", Sound.class);
super.preInit();
}
public void init(float endRadius, float x, float y, float growthRate, float warningTime) {
timer = warningTime;
maxTime = warningTime;
this.endRadius = endRadius;
setSize(2f*endRadius, 2f*endRadius);
setPosition(x-getWidth()/2f, y-getHeight()/2f);
this.growthRate = growthRate;
}
/**
* warningTime, endRadius, growthRate, x, y;
*/
@Override
public void init(HashMap<String, Float> params) {
timer = params.get("warningTime");
maxTime = timer;
endRadius = params.get("endRadius");
setSize(2f*endRadius, 2f*endRadius);
setPosition(params.get("x")-getWidth()/2f, params.get("y")-getHeight()/2f);
growthRate = params.get("growthRate");
super.init(params);
}
@Override
public void act(float delta) {
toFront();
if (begin) {
sprite.setSize(2*currentRadius, 2*currentRadius);
sprite.setColor(0f,0f,0f,1f);
} else {
sprite.setSize(2*endRadius, 2*endRadius);
sprite.setColor(1f,1f,1f,0.1f*(timer/maxTime));
}
if (timer > 0) {
timer -= delta;
} else {
begin = true;
if (currentRadius < endRadius) {
growCurrentRadius(delta*growthRate);
} else {
endRadius = -1f;
if (currentRadius > 0) {
growCurrentRadius(delta*-growthRate);
} else {
done = true;
}
}
}
super.act(delta);
}
@Override
public void reset() {
currentRadius = 0;
growthRate = 0;
timer = 0;
maxTime = 0;
endRadius = 0;
done = false;
begin = false;
setSize(0, 0);
super.reset();
}
public void growCurrentRadius(float radius) {
currentRadius += radius;
float length = (float) Math.sqrt(2*(currentRadius*currentRadius));
hitbox.setSize(length, length);
}
@Override
public EntityIndex getEntityType() {
return EntityIndex.VOID_CIRCLE;
}
@Override
public void collided(Entity entity) {
switch (entity.getEntityType()) {
case LASER:
sound.play(prefs.getFloat("fx vol"));
break;
default:
break;
}
}
@Override
public boolean isDead() {
return done;
}
@Override
public boolean playCollidePFX() {
return false;
}
@Override
public boolean playCollideSFX() {
return false;
}
}

View File

@@ -0,0 +1,61 @@
package zero1hd.rhythmbullet.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.GL20;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.ui.stages.CreativeHUD;
import zero1hd.rhythmbullet.ui.stages.GamePlayArea;
public class CreativeDebugScreen extends ScreenAdapter {
CreativeHUD creative;
GamePlayArea gamePlayArea;
InputMultiplexer inputs;
Preferences prefs;
public CreativeDebugScreen(Main core, MainMenu mainMenu) {
gamePlayArea = new GamePlayArea(core.getAssetManager(), core.getPrefs());
creative = new CreativeHUD(core, mainMenu, gamePlayArea);
inputs = new InputMultiplexer(creative, gamePlayArea);
this.prefs = core.getPrefs();
}
@Override
public void show() {
Gdx.input.setInputProcessor(inputs);
gamePlayArea.loadShaders(prefs);
super.show();
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
gamePlayArea.getViewport().apply();
gamePlayArea.act();
gamePlayArea.draw();
creative.getViewport().apply();
creative.act();
creative.draw();
super.render(delta);
}
@Override
public void resize(int width, int height) {
super.resize(width, height);
}
@Override
public void dispose() {
dispose();
super.dispose();
}
}

View File

@@ -0,0 +1,8 @@
package zero1hd.rhythmbullet.screens;
import com.badlogic.gdx.ScreenAdapter;
public class EndScreen extends ScreenAdapter {
public EndScreen() {
}
}

View File

@@ -0,0 +1,158 @@
package zero1hd.rhythmbullet.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.map.GamePlayMap;
import zero1hd.rhythmbullet.ui.stages.GameHUD;
import zero1hd.rhythmbullet.ui.stages.GamePlayArea;
public class GameScreen extends ScreenAdapter {
private GamePlayArea gameArea;
private GameHUD gameHUD;
public InputMultiplexer inputs;
public Main core;
private AudioData music;
SpriteBatch bgBatch;
private ShaderProgram bgShader;
private Texture background;
public GameScreen(Main polyJet, GamePlayMap gpm) {
core = polyJet;
// Overlay stuff
ImageButton pause = new ImageButton(core.getDefaultSkin().getDrawable("pause"),
core.getDefaultSkin().getDrawable("pause-down"));
pause.setPosition(Gdx.graphics.getWidth() - pause.getWidth() - 25,
Gdx.graphics.getHeight() - pause.getHeight() - 25);
pause.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
pause();
}
});
music = gpm.getMusicData();
gameArea = new GamePlayArea(polyJet.getAssetManager(), core.getPrefs());
gameArea.setAudioMap(gpm);
gameHUD = new GameHUD(polyJet.getDefaultSkin(), gpm.getMusicData().getPlaybackMusic(), gameArea.getMaxHealth());
inputs = new InputMultiplexer();
inputs.addProcessor(gameHUD);
inputs.addProcessor(gameArea);
background = core.getAssetManager().get("star_bg.png");
}
@Override
public void show() {
Gdx.input.setInputProcessor(inputs);
gameArea.loadShaders(core.getPrefs());
if (!gameHUD.isPaused()) {
music.getPlaybackMusic().play();
}
if (core.getPrefs().getBoolean("bg shader")) {
Gdx.app.debug("Shader", "using background shader");
bgShader = new ShaderProgram(Gdx.files.internal("shaders/bg.vsh"), Gdx.files.internal("shaders/bg.fsh"));
if (!bgShader.isCompiled()) {
System.err.println(bgShader.getLog());
System.exit(0);
}
if (bgShader.getLog().length()!=0) {
System.out.println(bgShader.getLog());
}
bgBatch = new SpriteBatch(2, bgShader);
} else {
bgBatch = new SpriteBatch(2);
}
super.show();
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0f, 0f, 0f, 0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
//Background stuff should literally span the whole screen so no matrice stuff
bgBatch.begin();
if (bgShader != null) {
bgBatch.setShader(bgShader);
bgShader.setUniformf("resolution", Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
if (music != null) {
bgShader.setUniformf("time", music.getPlaybackMusic().getPosition());
}
}
bgBatch.draw(background, 0f, 0f, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
bgBatch.end();
//actual game and hud
if (!gameHUD.isPaused()) {
gameHUD.setScore(gameArea.getScore());
gameArea.act(delta);
if (gameArea.getPolyjet().isDead()) {
end(false);
}
gameHUD.act(delta);
}
gameArea.getViewport().apply();
gameArea.draw();
gameHUD.getViewport().apply();
gameHUD.draw();
if (!music.getPlaybackMusic().isPlaying()) {
end(true);
}
super.render(delta);
}
private void end(boolean trueEnd) {
if (trueEnd) {
// TODO they didn't die
} else {
// TODO They done goofed and ended up dying.
}
}
@Override
public void dispose() {
gameHUD.dispose();
gameArea.dispose();
super.dispose();
}
@Override
public void pause() {
gameHUD.setPaused(true);
super.pause();
}
@Override
public void resize(int width, int height) {
gameArea.getViewport().update(width, height, true);
gameHUD.getViewport().update(width, height, true);
super.resize(width, height);
}
}

View File

@@ -0,0 +1,76 @@
package zero1hd.rhythmbullet.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.util.TransitionAdapter;
public class LoadingScreen extends ScreenAdapter {
private Stage stage;
Main core;
Image zero1HD;
Screen gotoScreen;
boolean reInit;
public LoadingScreen(Main core, Screen gotoScreen, boolean reInit, boolean timer) {
this.core = core;
this.gotoScreen = gotoScreen;
this.reInit = reInit;
stage = new Stage(new ScreenViewport());
core.getAssetManager().load("splashlogo.png", Texture.class);
core.getAssetManager().finishLoading();
zero1HD = new Image(this.core.getAssetManager().get("splashlogo.png", Texture.class));
zero1HD.setColor(0f,1f,1f,0f);
stage.addActor(zero1HD);
zero1HD.setPosition(stage.getWidth()/2 - zero1HD.getWidth()/2, stage.getHeight()/2 - zero1HD.getHeight()/2);
if (timer) {
zero1HD.addAction(Actions.sequence(Actions.color(Color.WHITE, 1f)));
}
core.queueAssets();
}
float count = 0;
@Override
public void render(float delta) {
Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(delta);
if (!zero1HD.hasActions() & core.getAssetManager().update()) {
Gdx.app.debug("Loading Screen", "queue has all been loaded. Action is done playing.");
zero1HD.remove();
core.generateFonts();
core.defineSkinStyles();
if (reInit) {
((TransitionAdapter) gotoScreen).postTransition();
}
core.setScreen(gotoScreen);
core.getAssetManager().unload("splashlogo.png");
core.getAssetManager().get("standard_thrust.p", ParticleEffect.class).flipY();
}
stage.draw();
super.render(delta);
}
@Override
public void resize(int width, int height) {
stage.getViewport().update(width, height, true);
super.resize(width, height);
}
}

View File

@@ -0,0 +1,139 @@
package zero1hd.rhythmbullet.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.ui.pages.CreditsPage;
import zero1hd.rhythmbullet.ui.pages.MainPage;
import zero1hd.rhythmbullet.ui.pages.MoreOptionsPage;
import zero1hd.rhythmbullet.ui.pages.OptionsPage;
import zero1hd.rhythmbullet.util.TransitionAdapter;
public class MainMenu extends ScreenAdapter implements TransitionAdapter {
public Stage stage;
private Vector3 targetPosition;
private MainPage mainPage;
private OptionsPage optionsPage;
private CreditsPage creditsPage;
private MoreOptionsPage moreOptionsPage;
private Main core;
public MainMenu(final Main core) {
this.core = core;
stage = new Stage(new ScreenViewport());
targetPosition = new Vector3(stage.getCamera().position);
}
public Screen postTransition() {
stage.clear();
mainPage = new MainPage(core, targetPosition);
mainPage.setPosition(0, 0);
stage.addActor(mainPage);
//End main menu
moreOptionsPage = new MoreOptionsPage(core, targetPosition);
optionsPage = new OptionsPage(core, targetPosition, moreOptionsPage);
optionsPage.setPosition(Gdx.graphics.getWidth(), 0);
stage.addActor(optionsPage);
creditsPage = new CreditsPage(core.getDefaultSkin());
creditsPage.setPosition(0, Gdx.graphics.getHeight());
stage.addActor(creditsPage);
moreOptionsPage.setPosition(1f*Gdx.graphics.getWidth(), -1f*Gdx.graphics.getHeight());
stage.addActor(moreOptionsPage);
stage.addListener(new InputListener() {
@Override
public boolean keyUp(InputEvent event, int keycode) {
if (keycode == Keys.ESCAPE) {
stage.unfocusAll();
if (targetPosition.x != 0.5f*Gdx.graphics.getWidth() || targetPosition.y != 0.5f*Gdx.graphics.getHeight()) {
targetPosition.x = 0.5f*Gdx.graphics.getWidth();
targetPosition.y = 0.5f*Gdx.graphics.getHeight();
}
moreOptionsPage.controlUnselect();
}
return super.keyUp(event, keycode);
}
});
stage.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
if (stage.hit(x, y, true) == null) {
stage.unfocusAll();
moreOptionsPage.controlUnselect();
}
super.clicked(event, x, y);
}
});
Gdx.app.debug("Post Transition", "Beginning screen setup for Main menu.");
return this;
}
@Override
public void show() {
Gdx.input.setInputProcessor(stage);
super.show();
}
@Override
public void hide() {
saveAll();
super.hide();
}
public void saveAll() {
if (optionsPage != null) {
optionsPage.saveOptions(core.getPrefs());
moreOptionsPage.getGraphicsSettings().save(core.getPrefs());
core.getPrefs().flush();
}
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
if (stage.getCamera().position.x != targetPosition.x || stage.getCamera().position.y != targetPosition.y) {
stage.getCamera().position.lerp(targetPosition, 0.25f);
}
super.render(delta);
}
@Override
public void resize(int width, int height) {
stage.getViewport().update(width, height, false);
targetPosition.x = width/2;
targetPosition.y = height/2;
super.resize(width, height);
}
@Override
public void dispose() {
stage.dispose();
super.dispose();
}
}

View File

@@ -0,0 +1,106 @@
package zero1hd.rhythmbullet.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.audio.Audio;
import zero1hd.rhythmbullet.ui.pages.AnalyzePage;
import zero1hd.rhythmbullet.ui.pages.MusicSelectionPage;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniListener;
import zero1hd.rhythmbullet.util.TransitionAdapter;
public class PreGameScreen extends ScreenAdapter implements TransitionAdapter, MiniListener {
Stage stage;
MusicSelectionPage ms;
AnalyzePage ap;
private Vector3 cameraPos;
private Main core;
public PreGameScreen(Main core) {
stage = new Stage(new ScreenViewport());
cameraPos = new Vector3(stage.getCamera().position);
this.core = core;
postTransition();
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.getViewport().apply();
stage.act();
stage.draw();
if (stage.getCamera().position.x != cameraPos.x) {
stage.getCamera().position.lerp(cameraPos, 0.25f);
}
super.render(delta);
}
@Override
public void resize(int width, int height) {
stage.getViewport().update(width, height);
super.resize(width, height);
}
@Override
public void handle(MiniEvents ID) {
switch (ID) {
case MUSIC_SELECTED:
cameraPos.x = 1.5f*Gdx.graphics.getWidth();
ap.setSong(Audio.getAudioData(ms.getSelectedMusic()), ms.getSelectedMusicInfo(), this);
break;
case BACK:
if (cameraPos.x == 1.5f*Gdx.graphics.getWidth()) {
cameraPos.x = 0.5f*Gdx.graphics.getWidth();
} else {
core.setScreen(new MainMenu(core).postTransition());
}
break;
default:
break;
}
}
@Override
public Screen postTransition() {
stage.clear();
ms = new MusicSelectionPage(core);
ms.miniSender.addListener(this);
ms.beginMusicSearch();
stage.addActor(ms);
ap = new AnalyzePage(core);
ap.miniSender.addListener(this);
ap.setPosition(Gdx.graphics.getWidth(), ap.getY());
stage.addActor(ap);
return this;
}
public void setPhase(int phase) {
cameraPos.x = Gdx.graphics.getWidth()*(phase + 0.5f);
}
@Override
public void show() {
Gdx.input.setInputProcessor(stage);
super.show();
}
@Override
public void dispose() {
stage.dispose();
super.dispose();
}
}

View File

@@ -0,0 +1,131 @@
package zero1hd.rhythmbullet.ui.builders;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.utils.FloatArray;
public class AudioGraph extends Actor {
Pixmap audioGraph;
Texture textureOfGraph;
FloatArray mainGraph;
FloatArray overlayGraph;
int dataIndex;
int displayMode;
public float normalDataG1 = 1f, normalDataG2 = 1f, avgG1 = 1f, avgG2 = 1f;
float scale;
public AudioGraph(int graphSizeW, int graphSizeH) {
audioGraph = new Pixmap(graphSizeW, graphSizeH, Format.RGBA8888);
audioGraph.setColor(0.1f, 0.1f, 0.1f, 0.75f);
audioGraph.fill();
textureOfGraph = new Texture(audioGraph);
setWidth(graphSizeW);
setHeight(graphSizeH);
scale = audioGraph.getHeight();
}
public void setAudioDataIndex(int audioDataIndex) {
this.dataIndex = audioDataIndex;
}
@Override
public void act(float delta) {
audioGraph.setColor(0f, 0f, 0f, 0.75f);
audioGraph.fill();
if (overlayGraph != null) {
if (Gdx.input.isKeyPressed(Keys.COMMA)) {
if (scale > 0.05f) {
scale -= 0.25f;
}
} else if (Gdx.input.isKeyPressed(Keys.PERIOD)) {
if (scale < audioGraph.getHeight()*2f) {
scale += 0.4f;
}
}
if (Gdx.input.isKeyJustPressed(Keys.M)) {
displayMode++;
if (displayMode != 3) {
Gdx.app.debug("Graph", "Switching to another graph.");
} else {
displayMode = 0;
}
}
}
if (Gdx.input.isKeyPressed(Keys.COMMA)) {
if (scale > 0.05f) {
scale -= 0.25f;
}
} else if (Gdx.input.isKeyPressed(Keys.PERIOD)) {
if (scale < audioGraph.getHeight()*2f) {
scale += 0.4f;
}
} else if (Gdx.input.isKeyJustPressed(Keys.SLASH)) {
scale = audioGraph.getHeight();
}
switch (displayMode) {
case 0:
audioGraph.setColor(1f, 0f, 0f, 0.75f);
for (int x = 0; x < audioGraph.getWidth(); x++) {
try {
audioGraph.drawLine(x, audioGraph.getHeight(), x, (int) (audioGraph.getHeight()-(mainGraph.get(dataIndex+x-audioGraph.getWidth()/2)/normalDataG1)*scale));
} catch (NullPointerException | IndexOutOfBoundsException e) {
}
audioGraph.drawLine(0, audioGraph.getHeight() - MathUtils.round(scale*(avgG1/normalDataG1)), audioGraph.getWidth(), audioGraph.getHeight() - MathUtils.round(scale*(avgG1/normalDataG1)));
}
case 1:
audioGraph.setColor(0f, 0f, 1f, 0.75f);
for (int x = 0; x < audioGraph.getWidth() -1; x++) {
try {
audioGraph.drawLine(x, audioGraph.getHeight(), x, (int) (audioGraph.getHeight()-(overlayGraph.get(dataIndex+x-audioGraph.getWidth()/2)/normalDataG2)*scale));
} catch (NullPointerException | IndexOutOfBoundsException e) {
}
audioGraph.drawLine(0, audioGraph.getHeight() - MathUtils.round(scale*(avgG2/normalDataG2)), audioGraph.getWidth(), audioGraph.getHeight() - MathUtils.round(scale*(avgG2/normalDataG2)));
}
break;
case 2:
audioGraph.setColor(1f, 0f, 0f, 0.75f);
for (int x = 0; x < audioGraph.getWidth(); x++) {
try {
audioGraph.drawLine(x, audioGraph.getHeight(), x, (int) (audioGraph.getHeight()-(mainGraph.get(dataIndex+x-audioGraph.getWidth()/2)/normalDataG1)*scale));
} catch (NullPointerException | IndexOutOfBoundsException e) {
}
}
audioGraph.drawLine(0, audioGraph.getHeight() - MathUtils.round(scale*(avgG1/normalDataG1)), audioGraph.getWidth(), audioGraph.getHeight() - MathUtils.round(scale*(avgG1/normalDataG1)));
break;
}
audioGraph.setColor(0f, 1f, 0f, 0.95f);
audioGraph.drawLine(audioGraph.getWidth()/2, 0, audioGraph.getWidth()/2, audioGraph.getHeight());
textureOfGraph.draw(audioGraph, 0, 0);
super.act(delta);
}
@Override
public void draw(Batch batch, float parentAlpha) {
batch.draw(textureOfGraph, getX(), getY(), getWidth(), getHeight());
super.draw(batch, parentAlpha);
}
public void setGraphingData(FloatArray dataSet1, FloatArray dataSet2) {
this.mainGraph = dataSet1;
this.overlayGraph = dataSet2;
if (dataSet2 == null) {
displayMode = 2;
} else {
displayMode = 0;
}
}
}

View File

@@ -0,0 +1,82 @@
package zero1hd.rhythmbullet.ui.builders;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.utils.FloatArray;
public class AudioGraphRelation extends Actor {
Pixmap audioGraph;
Texture textureOfGraph;
FloatArray mainGraph;
FloatArray overlayGraph;
int audioDataIndex;
public AudioGraphRelation(FloatArray mainGraph, FloatArray overlayGraph, int graphSizeW, int graphSizeH) {
audioGraph = new Pixmap(graphSizeW, graphSizeH, Format.RGBA8888);
audioGraph.setColor(0.1f, 0.1f, 0.1f, 0.75f);
audioGraph.fill();
textureOfGraph = new Texture(audioGraph);
setWidth(Gdx.graphics.getWidth());
setHeight(280);
this.mainGraph = mainGraph;
this.overlayGraph = overlayGraph;
}
public void setAudioDataIndex(int audioDataIndex) {
this.audioDataIndex = audioDataIndex;
}
float scale = 0.2f;
@Override
public void act(float delta) {
audioGraph.setColor(0f, 0f, 0f, 0.75f);
audioGraph.fill();
if (Gdx.input.isKeyPressed(Keys.COMMA)) {
if (scale > 0.02) {
scale -= 0.005f;
}
} else if (Gdx.input.isKeyPressed(Keys.PERIOD)) {
if (scale < 1) {
scale += 0.005f;
}
}
audioGraph.setColor(0f, 1f, 1f, 0.75f);
for (int x = 0; x < audioGraph.getWidth() -1; x++) {
try {
audioGraph.drawLine(x, (int) (audioGraph.getHeight()-mainGraph.get(audioDataIndex+x-audioGraph.getWidth()/2)*scale), x+1, (int) (audioGraph.getHeight()-mainGraph.get(audioDataIndex+x+1-audioGraph.getWidth()/2)*scale));
} catch (IndexOutOfBoundsException e) {
}
}
audioGraph.setColor(0f, 0.25f, 1f, 0.75f);
for (int x = 0; x < audioGraph.getWidth() -1; x++) {
try {
audioGraph.drawLine(x, (int) (audioGraph.getHeight()-overlayGraph.get(audioDataIndex+x-audioGraph.getWidth()/2)*scale), x+1, (int) (audioGraph.getHeight()-overlayGraph.get(audioDataIndex+x+1-audioGraph.getWidth()/2)*scale));
} catch (IndexOutOfBoundsException e) {
}
}
audioGraph.setColor(0f, 0f, 1, 0.95f);
audioGraph.drawLine(audioGraph.getWidth()/2, 0, audioGraph.getWidth()/2, audioGraph.getHeight());
textureOfGraph.draw(audioGraph, 0, 0);
super.act(delta);
}
@Override
public void draw(Batch batch, float parentAlpha) {
batch.draw(textureOfGraph, getX(), getY(), getWidth(), getHeight());
super.draw(batch, parentAlpha);
}
}

View File

@@ -0,0 +1,113 @@
package zero1hd.rhythmbullet.ui.builders;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Align;
public class GraphicsTable extends Table {
private Label resolutions, shaders;
private CheckBox glowShader, bgShader, invertShader;
private SetResolutionButton
_3840x2160,
_2560x1440,
_1920x1200,
_1920x1080,
_1280x800,
_1280x720,
_1366x768,
_800x480;
public GraphicsTable(Skin skin, final Preferences pref) {
align(Align.center);
defaults().space(10f);
shaders = new Label("OpenGL Shaders", skin);
add(shaders).fillX();
row();
invertShader = new CheckBox(" Invert Shader", skin, "expandable");
invertShader.setChecked(pref.getBoolean("invert shader", false));
add(invertShader).minHeight(shaders.getHeight());
row();
glowShader = new CheckBox(" Glow Shader", skin, "expandable");
glowShader.setChecked(pref.getBoolean("glow shader", true));
add(glowShader).minHeight(shaders.getHeight());
row();
bgShader = new CheckBox(" Background Shader", skin, "expandable");
bgShader.setChecked(pref.getBoolean("bg shader", true));
add(bgShader).minHeight(shaders.getHeight());
row();
resolutions = new Label("Optimized Resolutions", skin);
add(resolutions).left();
row();
TextButton fullscreen = new TextButton("Fullscreen", skin);
fullscreen.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (!Gdx.graphics.isFullscreen()) {
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
pref.putBoolean("fullscreen", true);
pref.flush();
}
}
});
add(fullscreen).fillX();
row();
_3840x2160 = new SetResolutionButton(3840, 2160, skin, pref);
add(_3840x2160).fillX();
row();
_2560x1440 = new SetResolutionButton(2560, 1440, skin, pref);
add(_2560x1440).fillX();
row();
_1920x1200 = new SetResolutionButton(1920, 1200, skin, pref);
add(_1920x1200).fillX();
row();
_1920x1080 = new SetResolutionButton(1920, 1080, skin, pref);
add(_1920x1080).fillX();
row();
_1280x800 = new SetResolutionButton(1280, 800, skin, pref);
add(_1280x800).fillX();
row();
_1280x720 = new SetResolutionButton(1280, 720, skin, pref);
add(_1280x720).fillX();
row();
_1366x768 = new SetResolutionButton(1366, 768, skin, pref);
add(_1366x768).fillX();
row();
_800x480 = new SetResolutionButton(800, 480, skin, pref);
add(_800x480).fillX();
row();
}
public void save(Preferences prefs) {
Gdx.app.debug("Preferences", "Saved shading values values.");
prefs.putBoolean("bg shader", bgShader.isChecked());
prefs.putBoolean("glow shader", glowShader.isChecked());
prefs.putBoolean("invert shader", invertShader.isChecked());
}
}

View File

@@ -0,0 +1,52 @@
package zero1hd.rhythmbullet.ui.builders;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
public class HealthBar extends WidgetGroup {
Image empty;
Image filler;
int health;
int maxHealth;
public HealthBar(Skin skin, int maxHealth) {
super();
filler = new Image(skin.getPatch("bar-fill"));
addActor(filler);
empty = new Image(skin.getPatch("bar-empty"));
addActor(empty);
this.maxHealth = maxHealth;
}
public void setHealth(int health) {
this.health = health;
filler.addAction(Actions.sizeTo(getWidth(), MathUtils.round((health/maxHealth)*getHeight()), 0.1f));;
}
@Override
public void setSize(float width, float height) {
empty.setSize(width, height);
filler.setSize(width, height);
super.setSize(width, height);
}
@Override
public void setWidth(float width) {
empty.setWidth(width);
filler.setWidth(width);
super.setWidth(width);
}
@Override
public void setHeight(float height) {
empty.setHeight(height);
super.setHeight(height);
}
}

View File

@@ -0,0 +1,64 @@
package zero1hd.rhythmbullet.ui.builders;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import zero1hd.rhythmbullet.controls.KeyMap;
public class KeySetter extends Actor {
TextureRegion keyIcon;
KeyMap keyMap;
public KeySetter(final KeyMap keyMap, final String control) {
this.keyMap = keyMap;
keyIcon = keyMap.getIcon(keyMap.stringToID(control));
setSize(keyIcon.getRegionWidth(), keyIcon.getRegionHeight());
InputListener keyListener = new InputListener() {
@Override
public boolean keyUp(InputEvent event, int keycode) {
getStage().setKeyboardFocus(null);
Gdx.app.debug("KeySetter", "input keycode received: " + keycode);
if (keycode != Keys.ESCAPE) {
Gdx.app.debug("keySetter", "input has been set to: " + Keys.toString(keycode));
if (setKey(keycode, control)) {
keyMap.updateKeys();
addAction(Actions.sequence(Actions.color(Color.GREEN, 0.2f), Actions.color(Color.WHITE, 0.2f)));
} else {
addAction(Actions.sequence(Actions.color(Color.RED, 0.2f), Actions.delay(0.1f), Actions.color(Color.WHITE, 0.2f)));
}
}
return super.keyUp(event, keycode);
}
};
addListener(keyListener);
}
public boolean setKey(int keycode, String control) {
if (keyMap.getIcon(keycode) != null) {
keyMap.getKeys().putInteger(control, keycode);
keyIcon = keyMap.getIcon(keycode);
return true;
} else {
return false;
}
}
@Override
public void draw(Batch batch, float parentAlpha) {
batch.setColor(getColor());
batch.draw(keyIcon, getX(), getY(), getWidth(), getHeight());
super.draw(batch, parentAlpha);
}
}

View File

@@ -0,0 +1,108 @@
package zero1hd.rhythmbullet.ui.builders;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Disposable;
import zero1hd.rhythmbullet.audio.AudioInfo;
public class MusicSelectable extends Button implements Disposable {
private Image imageIcon;
private ScrollText displayName;
private Label runTime;
private Label authorLabel;
private Label previousTopLabel;
private Label ratedDifficultyLabel;
private Skin skin;
private FileHandle musicFile;
private Texture defaultAlbumCover;
AudioInfo audioInfo;
public MusicSelectable(FileHandle musicFile, Preferences musicData, final Skin skin, Texture defaultAlbumC) {
super(skin, "info-button");
this.skin = skin;
this.defaultAlbumCover = defaultAlbumC;
this.musicFile = musicFile;
setName(musicFile.name());
audioInfo = new AudioInfo(musicFile, musicData);
defaults().pad(10f);
}
public void addInfoToPanel(float coverSize) {
displayName = new ScrollText(audioInfo.getSongName(), skin, true);
defaults().align(Align.top);
add(displayName).expandX().pad(0).fillX().padTop(10f).top().padBottom(10f);
row();
String formattedTime = "Run time: "+ String.valueOf(audioInfo.getDurationInSeconds()/60) + ":";
if (audioInfo.getDurationInSeconds() - (audioInfo.getDurationInSeconds()/60)*60 < 10) {
formattedTime = formattedTime.concat("0");
}
Table songInfoTable = new Table();
formattedTime = formattedTime.concat(String.valueOf(audioInfo.getDurationInSeconds() - (audioInfo.getDurationInSeconds()/60)*60));
runTime = new Label(formattedTime, skin, "sub-font", skin.getColor("default"));
songInfoTable.add(runTime).expandX().left();
songInfoTable.row();
authorLabel = new Label("Author: " + audioInfo.getAuthor(), skin, "sub-font", skin.getColor("default"));
songInfoTable.add(authorLabel).left();
songInfoTable.row();
previousTopLabel = new Label("High Score: " + (audioInfo.getPreviousTop() != -1 ? audioInfo.getPreviousTop() : "N/A"), skin, "sub-font", skin.getColor("default"));
songInfoTable.add(previousTopLabel).left();
songInfoTable.row();
ratedDifficultyLabel = new Label("Difficulty: " + (audioInfo.getRatedDifficulty() != -1 ? audioInfo.getRatedDifficulty() : "N/A"), skin, "sub-font", skin.getColor("default"));
songInfoTable.add(ratedDifficultyLabel).left();
songInfoTable.row();
row();
add(songInfoTable).expandY().center();
row();
audioInfo.setupTexture(defaultAlbumCover);
imageIcon = new Image(audioInfo.getAlbumCover());
if (audioInfo.isInvalidMusic()) {
imageIcon.setColor(Color.RED);
}
add(imageIcon).expandY().center().pad(15f).size(coverSize);
}
public FileHandle getMusicFile() {
return musicFile;
}
public AudioInfo getAudioInfo() {
return audioInfo;
}
@Override
public void dispose() {
audioInfo.dispose();
}
public boolean isMusicInvalid() {
return audioInfo.isInvalidMusic();
}
}

View File

@@ -0,0 +1,159 @@
package zero1hd.rhythmbullet.ui.builders;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Widget;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
public class ScrollText extends Widget {
Rectangle scissors = new Rectangle();
Rectangle clipBounds = new Rectangle();
GlyphLayout gLayout;
String text;
BitmapFont font;
private float fontHeight;
private float fontWidth;
private boolean scrollOnHover;
private boolean currentlyHovering;
private float textOffset;
private Vector2 coords;
public ScrollText(String text, Skin skin, boolean scrollOnHover) {
super();
setName(text);
this.scrollOnHover = scrollOnHover;
this.text = text;
font = skin.getFont("default-font");
font.setColor(skin.getColor("default"));
gLayout = new GlyphLayout(font, text);
fontHeight = gLayout.height;
fontWidth = gLayout.width;
coords = new Vector2();
addListener(new ClickListener() {
@Override
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
currentlyHovering = true;
super.enter(event, x, y, pointer, fromActor);
}
@Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
currentlyHovering = false;
super.exit(event, x, y, pointer, toActor);
}
@Override
public void clicked(InputEvent event, float x, float y) {
}
});
}
public ScrollText(String text, Skin skin, String fontName, Color color, boolean scrollOnHover) {
super();
setName(text);
this.scrollOnHover = scrollOnHover;
this.text = text;
font = skin.getFont(fontName);
font.setColor(color);
gLayout = new GlyphLayout(font, text);
fontHeight = gLayout.height;
fontWidth = gLayout.width;
coords = new Vector2();
addListener(new ClickListener() {
@Override
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
currentlyHovering = true;
super.enter(event, x, y, pointer, fromActor);
}
@Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
currentlyHovering = false;
super.exit(event, x, y, pointer, toActor);
}
@Override
public void clicked(InputEvent event, float x, float y) {
}
});
}
public float getFontHeight() {
return fontHeight;
}
public float getFontWidth() {
return fontWidth;
}
@Override
public void layout() {
setHeight(fontHeight+4);
clipBounds.setSize(getWidth(), getHeight()*1.5f);
super.layout();
}
@Override
public void act(float delta) {
if (fontWidth > clipBounds.getWidth()) {
if (scrollOnHover) {
if ((int) textOffset != 0 || currentlyHovering) {
if (textOffset < -fontWidth) {
textOffset = clipBounds.getWidth();
}
textOffset -= 60*delta;
}
} else {
if (textOffset < -fontWidth) {
textOffset = clipBounds.getWidth();
}
textOffset -= 60*delta;
}
}
super.act(delta);
}
@Override
public void draw(Batch batch, float parentAlpha) {
coords.x = getX();
coords.y = getY();
clipBounds.setX(coords.x);
clipBounds.setY(coords.y - 0.5f*getHeight());
getStage().calculateScissors(clipBounds, scissors);
batch.flush();
if (ScissorStack.pushScissors(scissors)) {
font.draw(batch, text, coords.x + textOffset, coords.y + getFontHeight());
batch.flush();
ScissorStack.popScissors();
};
}
@Override
public float getMinHeight() {
return fontHeight;
}
}

View File

@@ -0,0 +1,92 @@
package zero1hd.rhythmbullet.ui.builders;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Array;
import zero1hd.rhythmbullet.controls.KeyMap;
public class SetControls extends Table {
public SetControls(Skin skin, KeyMap keyMap) {
super(skin);
//first
Label forwardKeyLabel = new Label("Forward: ",skin);
forwardKeyLabel.setName(KeyMap.UP);
add(forwardKeyLabel).left();
KeySetter forwardKeySetter = new KeySetter(keyMap, KeyMap.UP);
add(forwardKeySetter).spaceRight(45f);
Label shootKeyLabel = new Label("Shoot: ", skin);
shootKeyLabel.setName(KeyMap.SHOOT);
add(shootKeyLabel).left();
KeySetter shootKeySetter = new KeySetter(keyMap, KeyMap.SHOOT);
add(shootKeySetter);
row();
//second
Label backwardKeyLabel = new Label("Backward: ", skin);
backwardKeyLabel.setName(KeyMap.DOWN);
add(backwardKeyLabel).left();
KeySetter backwardKeySetter = new KeySetter(keyMap, KeyMap.DOWN);
add(backwardKeySetter).spaceRight(45f);
Label sector1TPKeyLabel = new Label("Left Teleport", skin);
sector1TPKeyLabel.setName(KeyMap.FIRSTTHIRDTELEPORT);
add(sector1TPKeyLabel).left();
KeySetter Sector1TPKeySetter = new KeySetter(keyMap, KeyMap.FIRSTTHIRDTELEPORT);
add(Sector1TPKeySetter);
row();
Label leftKeyLabel = new Label("Left: ", skin);
leftKeyLabel.setName(KeyMap.LEFT);
add(leftKeyLabel).left();
KeySetter leftKeySetter = new KeySetter(keyMap, KeyMap.LEFT);
add(leftKeySetter).spaceRight(45f);
Label sector2TPKeyLabel = new Label("Middle Teleport: ", skin);
sector2TPKeyLabel.setName(KeyMap.SECONDTHIRDTELEPORT);
add(sector2TPKeyLabel).left();
KeySetter sector2TPKeySetter = new KeySetter(keyMap, KeyMap.SECONDTHIRDTELEPORT);
add(sector2TPKeySetter);
row();
Label rightKeyLabel = new Label("Right: ", skin);
rightKeyLabel.setName(KeyMap.RIGHT);
add(rightKeyLabel).left();
KeySetter rightKeySetter = new KeySetter(keyMap, KeyMap.RIGHT);
add(rightKeySetter).spaceRight(45f);
Label sector3TPKeyLabel = new Label("Right Teleport: ", skin);
sector3TPKeyLabel.setName(KeyMap.THIRDTHIRDTELEPORT);
add(sector3TPKeyLabel).left();
KeySetter sector3TPKeySetter = new KeySetter(keyMap, KeyMap.THIRDTHIRDTELEPORT);
add(sector3TPKeySetter);
addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
unselect();
getStage().setKeyboardFocus(event.getTarget());
event.getTarget().setColor(Color.ORANGE);
super.clicked(event, x, y);
}
});
}
public void unselect() {
Array<Actor> keys = getChildren();
for (int i = 0; i < keys.size; i++) {
keys.get(i).setColor(Color.WHITE);;
}
}
@Override
public void act(float delta) {
super.act(delta);
}
}

View File

@@ -0,0 +1,36 @@
package zero1hd.rhythmbullet.ui.builders;
import java.awt.Dimension;
import java.awt.Toolkit;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
public class SetResolutionButton extends TextButton {
public SetResolutionButton(final int width, final int height, Skin skin, final Preferences prefs) {
super(width + "x" + height, skin);
Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
if (screenDim.getWidth() < width || screenDim.getHeight() < height) {
setDisabled(true);
}
addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
Gdx.graphics.setWindowedMode(width, height);
prefs.putInteger("screen-width", width);
prefs.putInteger("screen-height", height);
prefs.putBoolean("fullscreen", false);
prefs.flush();
}
});
}
}

View File

@@ -0,0 +1,310 @@
package zero1hd.rhythmbullet.ui.pages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Align;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.AudioInfo;
import zero1hd.rhythmbullet.audio.map.GamePlayMap;
import zero1hd.rhythmbullet.audio.map.RhythmMapAlgorithm;
import zero1hd.rhythmbullet.screens.GameScreen;
import zero1hd.rhythmbullet.ui.builders.ScrollText;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniListener;
public class AnalyzePage extends Page implements MiniListener {
AudioAnalyzer audioAnalyzer;
AudioData music;
RhythmMapAlgorithm mapGenAlgorithm;
private Table songInfo;
private volatile Label[] info;
Table difficultyTable;
private Label diffTitle;
private Slider sensitivityRating;
private Label sensitivityRatingTitle;
private Slider speedModifier;
private Label speedModifierTitle;
private Slider healthModifier;
private Label healthModifierTitle;
private TextButton confirmDiffButton;
private boolean confirmed;
private Skin skin;
private Table beginTable;
private TextButton beginButton;
private TextButton back;
private Image loadingCircle;
private long startTime, endTime;
private Thread mapGenThread;
private Main core;
public AnalyzePage(Main core) {
super("Results", core.getDefaultSkin());
this.skin = core.getDefaultSkin();
this.core = core;
songInfo = new Table(skin);
songInfo.align(Align.top);
songInfo.pad(15f);
songInfo.setBackground(skin.getDrawable("large-pane"));
addActor(songInfo);
difficultyTable = new Table(skin);
difficultyTable.setBackground(skin.getDrawable("large-pane"));
addActor(difficultyTable);
diffTitle = new Label("Difficulty", skin);
difficultyTable.add(diffTitle).expandX().left();
difficultyTable.row();
sensitivityRating = new Slider(0f, 1f, 0.01f, false, skin);
sensitivityRating.setValue(0f);
sensitivityRating.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
sensitivityRatingTitle.setText("Base Difficulty: " + MathUtils.round(sensitivityRating.getValue()*100) +"%");
}
});
sensitivityRatingTitle = new Label("Base Difficulty: " + sensitivityRating.getValue(), skin, "sub-font", skin.getColor("default"));
difficultyTable.add(sensitivityRatingTitle);
difficultyTable.row();
difficultyTable.add(sensitivityRating).fillX();
difficultyTable.row();
speedModifier = new Slider(1f, 3f, 0.25f, false, skin);
speedModifier.setValue(1f);
speedModifier.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
speedModifierTitle.setText("Speed Modifier: x" + speedModifier.getValue());
}
});
speedModifierTitle = new Label("Speed Modifier: x" + speedModifier.getValue(), skin, "sub-font", skin.getColor("default"));
difficultyTable.add(speedModifierTitle);
difficultyTable.row();
difficultyTable.add(speedModifier).fillX();
difficultyTable.row();
healthModifier = new Slider(0f, 5f, 1f, false, skin);
healthModifier.setValue(0f);
healthModifier.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
healthModifierTitle.setText("Health modifier: +" + healthModifier.getValue());
}
});
healthModifierTitle = new Label("Health modifier: +" + healthModifier.getValue(), skin, "sub-font", skin.getColor("default"));
difficultyTable.add(healthModifierTitle);
difficultyTable.row();
difficultyTable.add(healthModifier).fillX().spaceBottom(15f);
difficultyTable.row();
confirmDiffButton = new TextButton("Confirm", skin);
confirmDiffButton.setDisabled(true);
confirmDiffButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
info[2].setText("Confirmed.");
confirmed = true;
confirmDiffButton.setDisabled(true);
sensitivityRating.setDisabled(true);
speedModifier.setDisabled(true);
healthModifier.setDisabled(true);
if (audioAnalyzer.containsData() ) {
finalizeData();
}
}
});
difficultyTable.add(confirmDiffButton);
difficultyTable.pack();
beginTable = new Table(skin);
beginTable.pad(15f);
beginButton = new TextButton("Begin", skin);
beginTable.add(beginButton);
beginTable.setBackground(skin.getDrawable("large-pane"));
beginTable.pack();
addActor(beginTable);
loadingCircle = new Image(core.getAssetManager().get("cybercircle1.png", Texture.class));
loadingCircle.setPosition((getWidth()-loadingCircle.getWidth())/2, (getHeightBelowTitle()-loadingCircle.getHeight())/2);
loadingCircle.setColor(0.8f,0.8f,0.8f,0.7f);
loadingCircle.setOrigin(loadingCircle.getWidth()/2, loadingCircle.getHeight()/2);
loadingCircle.addAction(Actions.forever(Actions.rotateBy(-360f, 4f)));
addActor(loadingCircle);
loadingCircle.toBack();
back = new TextButton("Back", skin);
back.setPosition(getWidth()-back.getWidth()-15f, getHeightBelowTitle());
back.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
miniSender.send(MiniEvents.BACK);
if (audioAnalyzer != null) {
audioAnalyzer.stop();
}
}
});
info = new Label[6];
for (int i = 0; i < info.length; i++) {
info[i] = new Label(null, skin, "sub-font", skin.getColor("default"));
}
addActor(back);
}
public void setSong(AudioData music, AudioInfo audioInfo, MiniListener listener) {
confirmed = false;
confirmDiffButton.setDisabled(false);
sensitivityRating.setDisabled(false);
speedModifier.setDisabled(false);
healthModifier.setDisabled(false);
songInfo.clear();
songInfo.defaults().align(Align.left | Align.top);
audioAnalyzer = new AudioAnalyzer();
audioAnalyzer.sender.addListener(this);
this.music = music;
audioAnalyzer.startAnalyticalThread(music);
songInfo.add(new ScrollText(audioInfo.getSongName(), skin, true)).expandX().fillX().spaceBottom(20f);
for (int i = 0; i < info.length; i++) {
info[i].setColor(1f, 1f, 1f, 0f);
info[i].setText(null);
songInfo.row();
songInfo.add(info[i]);
}
songInfo.pack();
songInfo.setWidth(getWidth()/2f);
songInfo.setPosition((getWidth()-songInfo.getWidth())/2f, (getHeightBelowTitle()-songInfo.getHeight())/2f);
difficultyTable.setPosition(songInfo.getX(), -difficultyTable.getHeight());
difficultyTable.setWidth(songInfo.getWidth());
beginTable.setPosition(difficultyTable.getX(), -beginTable.getHeight());
beginTable.setWidth(difficultyTable.getWidth());
startTime = System.currentTimeMillis();
info[0].addAction(Actions.color(Color.BLACK, 2.5f));
}
@Override
public void act(float delta) {
super.act(delta);
}
public boolean hasAudioData() {
if (music != null) {
return true;
} else {
return false;
}
}
public void clearAudioData() {
music = null;
}
@Override
public void handle(MiniEvents ID) {
switch (ID) {
case ANALYZER_ITERATED:
if (audioAnalyzer.getProgress() == 50) {
songInfo.addAction(Actions.moveTo(songInfo.getX(), getHeight()/2f, 0.75f, Interpolation.linear));
difficultyTable.addAction(Actions.moveTo(songInfo.getX(), songInfo.getY()-difficultyTable.getHeight(),0.8f, Interpolation.linear));
info[2].setText("Awaiting confirmation...");
info[2].addAction(Actions.color(Color.BLACK, 0.75f));
confirmDiffButton.setDisabled(false);
}
info[0].setText("Initial analysis: " + audioAnalyzer.getProgress() + "%");
break;
case SPECTRAL_FLUX_DONE:
endTime = System.currentTimeMillis();
info[1].setText("Done. Analyze time: " + ((endTime - startTime)/1000f) + "s");
info[1].addAction(Actions.color(Color.BLACK, 0.75f));
if (confirmed) {
finalizeData();
}
break;
case MUSIC_DATA_CLEANED:
info[3].setText("data cleaning done.");
info[4].addAction(Actions.color(Color.BLACK, 0.75f));
mapGenAlgorithm = new RhythmMapAlgorithm(audioAnalyzer, speedModifier.getValue(), healthModifier.getValue(), sensitivityRating.getValue());
mapGenAlgorithm.getSender().addListener(this);
mapGenThread = new Thread(mapGenAlgorithm);
mapGenThread.start();
startTime = System.currentTimeMillis();
break;
case MAPGEN_ITERATED:
info[4].setText("Generating map: " + mapGenAlgorithm.getProgress() + "%");
break;
case MAP_GENERATED:
endTime = System.currentTimeMillis();
info[5].setText("Done. Generation time: " + ((endTime - startTime)/1000f) + "s");
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
final GameScreen gameScreen = new GameScreen(core, mapGenAlgorithm.getMap());
beginButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
core.setScreen(gameScreen);
}
});
}
});
info[5].addAction(Actions.color(Color.BLACK, 0.75f));
songInfo.addAction(Actions.moveTo(songInfo.getX(), getHeightBelowTitle()-songInfo.getHeight(), 0.75f, Interpolation.linear));
difficultyTable.addAction(Actions.sequence(Actions.delay(0.4f), Actions.moveTo(songInfo.getX(), getHeightBelowTitle()-songInfo.getHeight()-difficultyTable.getHeight()-10f,0.8f, Interpolation.linear)));
beginTable.addAction(Actions.sequence(Actions.delay(0.5f), Actions.moveTo(difficultyTable.getX(), getHeightBelowTitle()-songInfo.getHeight()-difficultyTable.getHeight()-beginTable.getHeight()-20f,0.8f, Interpolation.linear)));
default:
break;
}
}
private void finalizeData() {
Gdx.app.debug("analyze", "confirmed data finalization.");
audioAnalyzer.runThresholdCleaning();
info[3].setText("finalizing data...");
info[3].addAction(Actions.color(Color.BLACK, 0.75f));
}
public GamePlayMap getMap() {
return mapGenAlgorithm.getMap();
}
}

View File

@@ -0,0 +1,26 @@
package zero1hd.rhythmbullet.ui.pages;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
public class CreditsPage extends Page {
public CreditsPage(Skin skin) {
Label title = new Label("Credits", skin, "large-font", skin.getColor("default"));
title.setPosition(15, getHeight()-title.getHeight()-15);
addActor(title);
Label subtitle = new Label("This game wouldn't be possible without these people.", skin, "sub-font", skin.getColor("default"));
subtitle.setPosition(title.getX(), title.getY()-subtitle.getHeight());
addActor(subtitle);
Label listOfNames = new Label(
"TheClimbingHippo (texture)\n"
+ "Crepitus (sound effects)\n"
+ "Neoqueto - Darktech LDR (font)\n"
+ "Rémi Lagast - Gasalt (font)\n"
+ "Timour Jgenti - Iron Maiden (font)", skin, "sub-font", skin.getColor("default"));
listOfNames.setPosition(subtitle.getX()+16, subtitle.getY()-listOfNames.getHeight()-10);
addActor(listOfNames);
}
}

View File

@@ -0,0 +1,112 @@
package zero1hd.rhythmbullet.ui.pages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.screens.PreGameScreen;
public class MainPage extends Page {
private Image polyjetTitle;
private Label polyJetVersion;
private TextButton options;
private Image cyberCircle;
private Label begin;
private TextButton quit;
private TextButton credits;
private WidgetGroup playButton;
public MainPage(final Main core, final Vector3 targetPosition) {
polyjetTitle = new Image(core.getAssetManager().get("PolyjetTitle.png", Texture.class));
polyjetTitle.setPosition(15, getHeight() - polyjetTitle.getHeight()-15);
addActor(polyjetTitle);
polyJetVersion = new Label("Version: " + Main.VERSION, core.getDefaultSkin(), "sub-font",
core.getDefaultSkin().getColor("default"));
polyJetVersion.setPosition(3, 3);
addActor(polyJetVersion);
options = new TextButton(" Options ", core.getDefaultSkin(), "left");
options.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
targetPosition.x = 1.5f * getWidth();
}
});
options.setPosition(-options.getWidth(), polyjetTitle.getY() - options.getHeight() - 30);
options.addAction(Actions.sequence(Actions.delay(0.25f), Actions.moveTo(0, options.getY(), 0.5f)));
addActor(options);
credits = new TextButton(" Credits ", core.getDefaultSkin(), "left");
credits.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
targetPosition.y = 1.5f * getHeight();
}
});
credits.setPosition(-credits.getWidth(), options.getY() - credits.getHeight() - 10);
credits.addAction(Actions.sequence(Actions.delay(0.5f), Actions.moveTo(0, credits.getY(), 0.5f)));
addActor(credits);
quit = new TextButton(" Quit ", core.getDefaultSkin(), "left");
quit.setPosition(-quit.getWidth(), credits.getY() - credits.getHeight() - 10);
quit.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
Gdx.app.exit();
}
});
quit.addAction(Actions.sequence(Actions.delay(0.75f), Actions.moveTo(0, quit.getY(), 0.5f)));
addActor(quit);
// begin play button
playButton = new WidgetGroup();
cyberCircle = new Image(core.getAssetManager().get("Tech-Circle1.png", Texture.class));
cyberCircle.setOrigin(cyberCircle.getWidth() / 2, cyberCircle.getHeight() / 2);
cyberCircle.setColor(0.7f, 0.7f, 0.7f, 0.8f);
cyberCircle.addAction(Actions.forever(Actions.rotateBy(-360f, 10f)));
playButton.addActor(cyberCircle);
playButton.setSize(cyberCircle.getWidth(), cyberCircle.getHeight());
begin = new Label("Play", core.getDefaultSkin(), "special-font", core.getDefaultSkin().getColor("default"));
begin.setColor(1f, 1f, 1f, 1f);
playButton.addActor(begin);
begin.setPosition(((playButton.getWidth() - begin.getWidth()) / 2)-10,
(playButton.getHeight() - begin.getHeight()) / 2);
playButton.setPosition(getWidth() - cyberCircle.getWidth() * 3 / 4, -cyberCircle.getHeight() / 4);
// begin animation of begin button
playButton.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
if (targetPosition.x == 0.5f * getWidth()) {
cyberCircle.addAction(
Actions.sequence(Actions.parallel(Actions.scaleBy(2f, 2f, 0.25f), Actions.fadeOut(0.25f)),
Actions.run(new Runnable() {
@Override
public void run() {
core.setScreen(new PreGameScreen(core));
}
}), Actions.parallel(Actions.scaleTo(1, 1), Actions.alpha(0.6f))));
}
super.clicked(event, x, y);
}
});
addActor(playButton);
// end play button
}
}

View File

@@ -0,0 +1,74 @@
package zero1hd.rhythmbullet.ui.pages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.controls.KeyMap;
import zero1hd.rhythmbullet.ui.builders.GraphicsTable;
import zero1hd.rhythmbullet.ui.builders.SetControls;
public class MoreOptionsPage extends Page {
private KeyMap keymap;
private ScrollPane controlsScroller;
private SetControls controlSetter;
private ScrollPane graphicsScroller;
private GraphicsTable graphicsSettings;
public MoreOptionsPage(Main core, final Vector3 targetLocation) {
keymap = new KeyMap(core);
TextButton backArrow = new TextButton("Back", core.getDefaultSkin());
backArrow.setPosition(15, getHeight()-backArrow.getHeight()-10);
backArrow.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
targetLocation.y = 0.5f*Gdx.graphics.getHeight();
}
});
addActor(backArrow);
controlSetter = new SetControls(core.getDefaultSkin(), keymap);
controlsScroller = new ScrollPane(controlSetter, core.getDefaultSkin());
controlsScroller.setFadeScrollBars(false);
controlsScroller.setSize(getWidth()-backArrow.getWidth()-backArrow.getX()-10, getHeight());
controlsScroller.setX(backArrow.getWidth()+10+backArrow.getX());
addActor(controlsScroller);
controlsScroller.setVisible(false);
graphicsSettings = new GraphicsTable(core.getDefaultSkin(), core.getPrefs());
graphicsScroller = new ScrollPane(graphicsSettings, core.getDefaultSkin());
graphicsScroller.setFadeScrollBars(false);
graphicsScroller.setSize(getWidth()-backArrow.getWidth()-backArrow.getX()-10, getHeight());
graphicsScroller.setX(backArrow.getWidth()+10+backArrow.getX());
addActor(graphicsScroller);
graphicsScroller.setVisible(false);
}
public void controlUnselect() {
controlSetter.unselect();
}
public void setControlType(byte type) {
switch (type) {
case 0:
controlsScroller.setVisible(true);
graphicsScroller.setVisible(false);
break;
case 1:
controlsScroller.setVisible(false);
graphicsScroller.setVisible(true);
break;
}
}
public GraphicsTable getGraphicsSettings() {
return graphicsSettings;
}
}

View File

@@ -0,0 +1,155 @@
package zero1hd.rhythmbullet.ui.pages;
import java.io.File;
import java.io.FilenameFilter;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.audio.AudioInfo;
import zero1hd.rhythmbullet.ui.builders.MusicSelectable;
import zero1hd.rhythmbullet.ui.windows.LoadingWindow;
import zero1hd.rhythmbullet.ui.windows.NoticeWindow;
import zero1hd.rhythmbullet.util.MiniEvents;
public class MusicSelectionPage extends Page {
private volatile Table musicChoices;
Preferences musicFileAnnotation;
private Main core;
private volatile ScrollPane musicChoiceScroller;
private volatile LoadingWindow loadingWindow;
protected volatile boolean cancel;
private TextButton back;
private FileHandle selectedMusic;
private AudioInfo selectedMusicInfo;
public MusicSelectionPage(final Main core) {
super("Select music", core.getDefaultSkin());
this.core = core;
musicFileAnnotation = Gdx.app.getPreferences("music_file_annotation");
back = new TextButton("Back", core.getDefaultSkin());
back.setPosition(getWidth()-back.getWidth()-15f, getHeightBelowTitle());
back.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
miniSender.send(MiniEvents.BACK);
cancel = true;
}
});
addActor(back);
loadingWindow = new LoadingWindow(core.getDefaultSkin(), "tinted", true, core.getAssetManager(), core.getPrefs().getFloat("fx vol"));
loadingWindow.setPosition((getWidth()-loadingWindow.getWidth())/2f, (getHeight()-loadingWindow.getHeight())/2f);
addActor(loadingWindow);
loadingWindow.playOpenSound();
loadingWindow.setMovable(false);
loadingWindow.setModal(true);
musicChoices = new Table();
musicChoices.defaults().pad(10f);
musicChoiceScroller = new ScrollPane(musicChoices);
musicChoiceScroller.setScrollingDisabled(false, true);
musicChoiceScroller.setSize(getWidth(), getHeight()-(getHeight()-back.getY()));
addActor(musicChoiceScroller);
loadingWindow.toFront();
back.toFront();
}
@Override
public void act(float delta) {
back.toFront();
super.act(delta);
}
public void beginMusicSearch() {
new Thread(new Runnable() {
@Override
public void run() {
Logger.getLogger("org.jaudiotagger").setLevel(Level.SEVERE);
FileHandle[] musicFiles = new FileHandle(core.getPrefs().getString("music dir")).list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
if (name.endsWith("mp3") || name.endsWith("wav")) {
return true;
}
return false;
}
});
if (musicFiles.length > 0) {
for (int music = 0; music < musicFiles.length && !cancel; music++) {
final MusicSelectable selectable = new MusicSelectable(musicFiles[music], musicFileAnnotation, core.getDefaultSkin(), core.getAssetManager().get("defaultCover.png", Texture.class));
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
Gdx.app.debug("Music Search Thread", "Finished loading: " + selectable.getName());
musicChoices.add(selectable).prefSize(panelWidthCalc(getWidth()), musicChoiceScroller.getHeight());
selectable.addInfoToPanel(panelWidthCalc(getWidth()) - 20f);
selectable.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (!selectable.isMusicInvalid()) {
selectedMusic = selectable.getMusicFile();
selectedMusicInfo = selectable.getAudioInfo();
miniSender.send(MiniEvents.MUSIC_SELECTED);
} else {
//Play "no" sound
}
}
});
}
});
Gdx.app.debug("Music Search Thread", "Completed: " + music);
int prog = (int) (100f*music/(musicFiles.length-1f));
loadingWindow.setProgress(prog);
}
loadingWindow.remove();
} else {
NoticeWindow notice = new NoticeWindow(core.getDefaultSkin(), "default", "No song's found in:\n\"" + core.getPrefs().getString("music dir") + "\"\nTo change the search directory, go to game options.", core.getPrefs().getLong("fx vol"), core.getAssetManager());
notice.setSize(0.6f*getWidth(), 0.6f*getHeight());
notice.setPosition((getWidth()-notice.getWidth())/2f, (getHeight()-notice.getHeight())/2f);
notice.setModal(true);
notice.setMovable(false);
loadingWindow.remove();
addActor(notice);
notice.playOpenSound();
}
}
}).start();
}
public float panelWidthCalc(float origWidth) {
return (float) (Math.sqrt(getWidth()*35f)+80f);
}
public FileHandle getSelectedMusic() {
return selectedMusic;
}
public AudioInfo getSelectedMusicInfo() {
return selectedMusicInfo;
}
}

View File

@@ -0,0 +1,38 @@
package zero1hd.rhythmbullet.ui.pages;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
public class MusicStatusPage extends Page {
Label statusText;
Image loading;
Button back;
public MusicStatusPage(Skin skin, final Vector3 v3) {
super("Info", skin);
back = new Button(skin, "arrow-button");
back.setPosition(15f, (getHeight()-back.getHeight())/2 -15);
back.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
v3.x = 0.5f*getWidth();
}
});
addActor(back);
loading = new Image(skin, "loading");
loading.setPosition((getWidth()-loading.getWidth())/2, (getHeight()-loading.getHeight())/2);
loading.setOrigin(loading.getWidth()/2, loading.getHeight()/2);
loading.addAction(Actions.forever(Actions.rotateBy(-360f, 2f)));
addActor(loading);
}
}

View File

@@ -0,0 +1,162 @@
package zero1hd.rhythmbullet.ui.pages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.screens.CreativeDebugScreen;
import zero1hd.rhythmbullet.screens.MainMenu;
public class OptionsPage extends Page {
Table optionsTable = new Table();
private ProgressBar musicVolSlider;
private ProgressBar fxVolSlider;
private TextField directoryField;
private Main core;
private byte goToScreen;
public OptionsPage(final Main core, final Vector3 targetPosition, final MoreOptionsPage moreOptionsPage) {
this.core = core;
optionsTable.defaults().spaceLeft(40f).padTop(5f).padBottom(5f).left();
Label optionGeneralTitle = new Label("General", core.getDefaultSkin(), "large-font", core.getDefaultSkin().getColor("default"));
optionsTable.add(optionGeneralTitle).left().spaceBottom(10f);
optionsTable.row();
Label musicVolSliderLabel = new Label("Music Volume: ", core.getDefaultSkin());
optionsTable.add(musicVolSliderLabel).padRight(12f).left();
musicVolSlider = new Slider(0, 100, 0.1f, false, core.getDefaultSkin());
musicVolSlider.setValue(core.getPrefs().getFloat("music vol", 100f));
optionsTable.add(musicVolSlider).prefWidth(790).left();
final Label musicVolPercentage = new Label(MathUtils.round(musicVolSlider.getValue()) + "%", core.getDefaultSkin());
musicVolSlider.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
musicVolPercentage.setText(MathUtils.round(musicVolSlider.getValue()) + "%");
}
});
optionsTable.add(musicVolPercentage).expandX();
optionsTable.row();
Label fxVolSliderLabel = new Label("FX Volume: ", core.getDefaultSkin());
optionsTable.add(fxVolSliderLabel).padRight(12f).left();
fxVolSlider = new Slider(0, 100, 1, false, core.getDefaultSkin());
fxVolSlider.setValue(core.getPrefs().getFloat("fx vol", 100f));
optionsTable.add(fxVolSlider).prefWidth(790);
final Label fxVolPercentage = new Label(MathUtils.round(fxVolSlider.getValue()) + "%", core.getDefaultSkin());
fxVolSlider.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
fxVolPercentage.setText(MathUtils.round(fxVolSlider.getValue()) + "%");
}
});
optionsTable.add(fxVolPercentage);
optionsTable.row();
Label musicDirectoryLabel = new Label("Music Directory: ", core.getDefaultSkin());
optionsTable.add(musicDirectoryLabel).left();
directoryField = new TextField(null, core.getDefaultSkin());
directoryField.setText(core.getPrefs().getString("music dir", System.getProperty("user.home")+System.getProperty("file.separator")+"Music"));
optionsTable.add(directoryField).prefWidth(810).left();
optionsTable.row();
Label debugCodeLabel = new Label("Debug Code: ", core.getDefaultSkin());
optionsTable.add(debugCodeLabel).left();
final TextField debugCodeField = new TextField(null, core.getDefaultSkin());
debugCodeField.addListener(new InputListener() {
@Override
public boolean keyUp(InputEvent event, int keycode) {
if (keycode == Keys.ENTER) {
Gdx.app.debug("Debug Field", debugCodeField.getText());
if (debugCodeField.getText().equals("creative")) {
Gdx.app.debug("Debug Field", "going to creative test room...");
goToScreen = 1;
}
}
return super.keyUp(event, keycode);
}
});
optionsTable.add(debugCodeField).prefWidth(810).left();
optionsTable.top();
//Back button
TextButton backButton = new TextButton("Back", core.getDefaultSkin());
backButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
targetPosition.x = 0.5f*Gdx.graphics.getWidth();
}
});
backButton.setPosition(10, getHeight()-backButton.getHeight()-18);
addActor(backButton);
optionsTable.setPosition(backButton.getX()+ 20 + backButton.getWidth(), 0);
optionsTable.setSize(getWidth()-backButton.getWidth()-10-20-10, getHeight());
addActor(optionsTable);
optionsTable.row();
TextButton keybindSettings = new TextButton("Set Controls", core.getDefaultSkin());
keybindSettings.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
moreOptionsPage.setControlType((byte) 0);
targetPosition.y = -0.5f*Gdx.graphics.getHeight();
}
});
optionsTable.add(keybindSettings).colspan(2).fill();
optionsTable.row();
TextButton graphicsSettings = new TextButton("Graphics", core.getDefaultSkin());
graphicsSettings.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
moreOptionsPage.setControlType((byte) 1);
targetPosition.y = -0.5f*Gdx.graphics.getHeight();
}
});
optionsTable.add(graphicsSettings).colspan(2).fill();
}
public void saveOptions(Preferences prefs) {
Gdx.app.debug("Preferences", "Saved all basic options page values.");
prefs.putFloat("music vol", musicVolSlider.getValue());
prefs.putFloat("fx vol", fxVolSlider.getValue());
prefs.putString("music dir", directoryField.getText());
}
@Override
public void act(float delta) {
if (core.getAssetManager().update() && goToScreen != 0) {
switch (goToScreen) {
case 1:
core.setScreen(new CreativeDebugScreen(core, (MainMenu) core.getScreen()));
}
goToScreen = 0;
}
super.act(delta);
}
}

View File

@@ -0,0 +1,34 @@
package zero1hd.rhythmbullet.ui.pages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import zero1hd.rhythmbullet.util.MiniSender;
public class Page extends Group {
private Label pageTitle;
public MiniSender miniSender;
public Page() {
setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
miniSender = new MiniSender();
setTouchable(Touchable.childrenOnly);
}
public Page(String titleText, Skin skin) {
miniSender = new MiniSender();
setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
setTouchable(Touchable.childrenOnly);
pageTitle = new Label(titleText, skin, "large-font", skin.getColor("default"));
pageTitle.setPosition(18f, getHeight()-pageTitle.getHeight()-15f);
addActor(pageTitle);
}
public float getHeightBelowTitle() {
return pageTitle.getY();
}
}

View File

@@ -0,0 +1,44 @@
package zero1hd.rhythmbullet.ui.pages;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
public class StatPage extends Page {
private Table table;
private Label winLabel;
private Label finalScore, damageTaken, enemiesKilled, shotsTaken, shotsMissed, accuracy;
public StatPage(Skin skin, int score, int damageTake, int enemiesKilled, int shotsTaken, int shotsMissed, int accuracy) {
table = new Table(skin);
addActor(table);
table.setFillParent(true);
winLabel = new Label("Win!", skin);
table.add(winLabel);
table.row();
this.finalScore = new Label("Your score: " + score, skin, "sub-font", skin.getColor("default"));
table.add(this.finalScore);
table.row();
this.damageTaken = new Label("Damage Taken: " + damageTake, skin, "sub-font", skin.getColor("default"));
table.add(this.damageTaken);
table.row();
this.enemiesKilled = new Label("Enemies slayed: " + enemiesKilled, skin, "sub-font", skin.getColor("default"));
table.add(this.enemiesKilled);
table.row();
this.shotsTaken = new Label("Shots taken: " + shotsTaken, skin, "sub-font", skin.getColor("default"));
table.add(this.shotsTaken);
table.row();
this.shotsMissed = new Label("Shots missed: " + shotsMissed, skin, "sub-font", skin.getColor("default"));
table.add(this.shotsMissed);
table.row();
this.accuracy = new Label("Accuracy: " + accuracy, skin, "sub-font", skin.getColor("default"));
table.add(this.accuracy);
}
}

View File

@@ -0,0 +1,285 @@
package zero1hd.rhythmbullet.ui.stages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.audio.map.RhythmMapAlgorithm;
import zero1hd.rhythmbullet.screens.MainMenu;
import zero1hd.rhythmbullet.ui.windows.BassUMGraphWindow;
import zero1hd.rhythmbullet.ui.windows.BeatViewer;
import zero1hd.rhythmbullet.ui.windows.DifficultyWindow;
import zero1hd.rhythmbullet.ui.windows.FPSWindow;
import zero1hd.rhythmbullet.ui.windows.MGraphWindow;
import zero1hd.rhythmbullet.ui.windows.MusicController;
import zero1hd.rhythmbullet.ui.windows.MusicSelector;
import zero1hd.rhythmbullet.ui.windows.SpawnerWindow;
import zero1hd.rhythmbullet.ui.windows.VolumeWindow;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniListener;
public class CreativeHUD extends Stage implements MiniListener {
MusicController musicPlayBackControls;
MusicSelector musicSelector;
FPSWindow fpsViewer;
BeatViewer beatViewer;
BassUMGraphWindow bassUMgraphWindow;
MGraphWindow mGraphWindow;
VolumeWindow volumeWindow;
SpawnerWindow spawnerWindow;
DifficultyWindow diffWindow;
AudioAnalyzer analyzer;
RhythmMapAlgorithm mapGen;
Window toolbox;
GamePlayArea gpa;
public CreativeHUD(final Main core, final MainMenu mainMenu, final GamePlayArea gpa) {
this.gpa = gpa;
musicSelector = new MusicSelector("Select Audio File", core.getDefaultSkin(), core.getPrefs().getString("music dir"), "default");
musicSelector.miniSender.addListener(this);
musicSelector.refresh();
fpsViewer = new FPSWindow("FPS", core.getDefaultSkin());
beatViewer = new BeatViewer("Beat", core.getDefaultSkin());
bassUMgraphWindow = new BassUMGraphWindow("Bass/UM Peak Values", core.getDefaultSkin());
mGraphWindow = new MGraphWindow("Midrange Peak Values", core.getDefaultSkin());
volumeWindow = new VolumeWindow("Volume adjustments", core.getDefaultSkin(), core.getPrefs());
spawnerWindow = new SpawnerWindow("Spawn Tool", core.getDefaultSkin(), gpa.ec, gpa);
diffWindow = new DifficultyWindow(core.getDefaultSkin());
//Back button
TextButton backButton = new TextButton("Back", core.getDefaultSkin());
backButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
dispose();
core.setScreen(mainMenu);
}
});
backButton.setPosition(10, Gdx.graphics.getHeight()-backButton.getHeight()-10);
addActor(backButton);
toolbox = new Window("Tools", core.getDefaultSkin(), "tinted");
toolbox.defaults().pad(5f);
Table toolboxToolSet = new Table(core.getDefaultSkin());
toolboxToolSet.defaults().space(5f);
final CheckBox musicSelectorCheckbox = new CheckBox(" Music selector", core.getDefaultSkin());
musicSelectorCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (musicSelectorCheckbox.isChecked()) {
addActor(musicSelector);
} else {
musicSelector.remove();
}
}
});
toolboxToolSet.add(musicSelectorCheckbox);
toolboxToolSet.row();
musicPlayBackControls = new MusicController(core.getDefaultSkin());
final CheckBox musicPlayBackCheckbox = new CheckBox(" Playback controls", core.getDefaultSkin());
musicPlayBackCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (musicPlayBackCheckbox.isChecked()) {
addActor(musicPlayBackControls);
} else {
musicPlayBackControls.remove();
}
}
});
toolboxToolSet.add(musicPlayBackCheckbox);
toolboxToolSet.row();
final CheckBox beatViewerCheckbox = new CheckBox(" Beat viewer", core.getDefaultSkin());
beatViewerCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (beatViewerCheckbox.isChecked()) {
addActor(beatViewer);
} else {
beatViewer.remove();
}
}
});
toolboxToolSet.add(beatViewerCheckbox);
toolboxToolSet.row();
final CheckBox fpsViewerCheckbox = new CheckBox(" FPS", core.getDefaultSkin());
fpsViewerCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (fpsViewerCheckbox.isChecked()) {
addActor(fpsViewer);
} else {
fpsViewer.remove();
}
}
});
toolboxToolSet.add(fpsViewerCheckbox);
toolboxToolSet.row();
final CheckBox peakGraphCheckbox = new CheckBox(" Peak Graphs", core.getDefaultSkin());
peakGraphCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (peakGraphCheckbox.isChecked()) {
addActor(bassUMgraphWindow);
addActor(mGraphWindow);
} else {
bassUMgraphWindow.remove();
mGraphWindow.remove();
}
}
});
toolboxToolSet.add(peakGraphCheckbox);
toolboxToolSet.row();
final CheckBox volumeMixerCheckbox = new CheckBox(" Volume", core.getDefaultSkin());
volumeMixerCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (volumeMixerCheckbox.isChecked()) {
addActor(volumeWindow);
} else {
volumeWindow.remove();
}
}
});
toolboxToolSet.add(volumeMixerCheckbox);
toolboxToolSet.row();
final CheckBox spawnToolCheckBox = new CheckBox(" Spawn Tool", core.getDefaultSkin());
spawnToolCheckBox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (spawnToolCheckBox.isChecked()) {
addActor(spawnerWindow);
} else {
spawnerWindow.remove();
}
}
});
toolboxToolSet.add(spawnToolCheckBox);
toolboxToolSet.row();
final CheckBox diffAdjusterCheckBox = new CheckBox(" Difficulty", core.getDefaultSkin());
diffAdjusterCheckBox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (diffAdjusterCheckBox.isChecked()) {
addActor(diffWindow);
} else {
diffWindow.remove();
}
}
});
toolboxToolSet.add(diffAdjusterCheckBox);
ScrollPane scroller = new ScrollPane(toolboxToolSet, core.getDefaultSkin());
toolbox.add(scroller).expand().fill();
toolbox.setSize(300, 300);
addActor(toolbox);
addListener(new InputListener() {
@Override
public boolean keyUp(InputEvent event, int keycode) {
if (keycode == Keys.ENTER || keycode == Keys.ESCAPE) {
setKeyboardFocus(null);
}
return super.keyUp(event, keycode);
}
});
toolboxToolSet.pack();
toolbox.pack();
}
@Override
public void act(float delta) {
super.act(delta);
}
@Override
public void dispose() {
if (analyzer != null) {
analyzer.audioData.dispose();
}
super.dispose();
}
@Override
public void handle(MiniEvents ID) {
switch (ID) {
case BACK:
break;
case MUSIC_SELECTED:
beatViewer.setMusic(null, null);
volumeWindow.setMusic(null);
bassUMgraphWindow.setData(null, null, null);
mGraphWindow.setData(null, null, null);
if (musicPlayBackControls.getAudiofile() != null) {
musicPlayBackControls.getAudiofile().dispose();
}
musicPlayBackControls.setAudiofile(null);
analyzer = new AudioAnalyzer();
analyzer.sender.addListener(this);
analyzer.startAnalyticalThread(musicSelector.getSelectedMusic());
break;
case SPECTRAL_FLUX_DONE:
analyzer.runThresholdCleaning();
break;
case MUSIC_DATA_CLEANED:
if (analyzer != null && analyzer.isFinalized()) {
mapGen = new RhythmMapAlgorithm(analyzer, diffWindow.getSpeedModifier(), diffWindow.getHealthModifier(), diffWindow.getSensitivityVal());
mapGen.getSender().addListener(this);
Thread mapGenThread = new Thread(mapGen);
mapGenThread.start();
}
break;
case MAP_GENERATED:
Gdx.app.debug("creative", "successfully generated map.");
musicPlayBackControls.setAudiofile(analyzer.getAudioData());
volumeWindow.setMusic(analyzer.getAudioData());
beatViewer.setMusic(analyzer.getAudioData(), analyzer);
bassUMgraphWindow.setData(analyzer.getBassPeaks(), analyzer.getUMPeaks(), analyzer.getAudioData());
bassUMgraphWindow.getGraph().avgG1 = analyzer.getBassAvg();
bassUMgraphWindow.getGraph().normalDataG1 = analyzer.getBassMaxValue();
bassUMgraphWindow.getGraph().avgG2 = analyzer.getUmAvg();
bassUMgraphWindow.getGraph().normalDataG2 = analyzer.getUMMaxValue();
mGraphWindow.setData(analyzer.getmPeaks(), null, analyzer.getAudioData());
mGraphWindow.getGraph().normalDataG1 = analyzer.getmMaxValue();
mGraphWindow.getGraph().avgG1 = analyzer.getmAvg();
gpa.setAudioMap(mapGen.getMap());
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,130 @@
package zero1hd.rhythmbullet.ui.stages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.ui.builders.HealthBar;
import zero1hd.rhythmbullet.ui.windows.FPSWindow;
import zero1hd.rhythmbullet.ui.windows.PauseMenu;
public class GameHUD extends Stage {
private Label score;
private ImageButton pause;
private boolean paused;
private FPSWindow fpsWindow;
private PauseMenu pauseMenu;
private HealthBar healthBar;
private Music music;
public GameHUD(Skin skin, Music music, int maxHealth) {
super();
this.music = music;
score = new Label("Score: 0", skin, "default-font", Color.WHITE);
score.setPosition(10f, Gdx.graphics.getHeight()-score.getHeight() - 10f);
addActor(score);
pause = new ImageButton(skin.getDrawable("pause"),
skin.getDrawable("pause-down"));
pause.setPosition(Gdx.graphics.getWidth() - pause.getWidth() - 15f,
Gdx.graphics.getHeight() - pause.getHeight() - 15f);
pause.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
setPaused(true);
}
});
addActor(pause);
fpsWindow = new FPSWindow("FPS", skin);
fpsWindow.setPosition(15f, 15f);
pauseMenu = new PauseMenu(skin);
pauseMenu.getResumeButton().addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
setPaused(false);
}
});
pauseMenu.setPosition((Gdx.graphics.getWidth()-pauseMenu.getWidth())/2f, (Gdx.graphics.getHeight()-pauseMenu.getHeight())/2f);
healthBar = new HealthBar(skin, maxHealth);
healthBar.setSize(20f, Gdx.graphics.getHeight()/3);
healthBar.setHealth(maxHealth);
healthBar.setPosition(Gdx.graphics.getWidth()-healthBar.getWidth() -10f, (Gdx.graphics.getHeight()-healthBar.getHeight())/2f);
addActor(healthBar);
}
/**
* sets the label for scoring to the designated score
* @param score designated score
*/
public void setScore(int score) {
this.score.setText("Score: " + score);
}
/**
* returns current score by use of substring
* @return the current score value
*/
public int getScore() {
return Integer.valueOf(score.getText().substring(7));
}
public void setPaused(boolean paused) {
if (paused) {
addActor(pauseMenu);
music.pause();
} else {
pauseMenu.remove();
music.play();
}
this.paused = paused;
}
/**
* toggle's between the two states of paused and unpaused
* @return whatever the new game state is (true for paused)
*/
public boolean togglePause() {
if (isPaused()) {
setPaused(false);
} else {
setPaused(true);
}
return isPaused();
}
public boolean isPaused() {
return paused;
}
@Override
public boolean keyUp(int keycode) {
switch (keycode) {
case Keys.F3:
if (fpsWindow.hasParent()) {
fpsWindow.remove();
} else {
addActor(fpsWindow);
}
break;
case Keys.ESCAPE:
togglePause();
break;
default:
break;
}
return false;
}
}

View File

@@ -0,0 +1,244 @@
package zero1hd.rhythmbullet.ui.stages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.FitViewport;
import zero1hd.rhythmbullet.Main;
import zero1hd.rhythmbullet.audio.map.EntitySpawnInfo;
import zero1hd.rhythmbullet.audio.map.GamePlayMap;
import zero1hd.rhythmbullet.audio.map.MapWindowData;
import zero1hd.rhythmbullet.controls.KeyMap;
import zero1hd.rhythmbullet.entity.CollisionDetector;
import zero1hd.rhythmbullet.entity.Entity;
import zero1hd.rhythmbullet.entity.EntityController;
import zero1hd.rhythmbullet.entity.EntityIndex;
import zero1hd.rhythmbullet.entity.ally.Laser;
import zero1hd.rhythmbullet.entity.ally.PolyJetEntity;
public class GamePlayArea extends Stage {
public PolyJetEntity polyjet;
private GamePlayMap audioMap;
public EntityController ec;
private CollisionDetector collisionDetector;
private int maxHealth = 100;
private float yTeleport = Main.GAME_AREA_HEIGHT/2;
private int score;
private ShaderProgram glowShader;
private FrameBuffer blurTarget;
TextureRegion fboRegion;
private int fboSize;
public GamePlayArea(AssetManager assetManager, Preferences prefs) {
super(new FitViewport(Main.GAME_AREA_WIDTH, Main.GAME_AREA_HEIGHT));
Gdx.app.debug("Game Area", "new area created");
polyjet = new PolyJetEntity(assetManager, 25f, 25f, "standard");
ec = new EntityController(assetManager, prefs, this);
collisionDetector = new CollisionDetector(ec.activeEnemies, ec.activeAllies, assetManager, prefs);
ec.activeAllies.add(polyjet);
addActor(polyjet);
}
public void setAudioMap(GamePlayMap audioMap) {
this.audioMap = audioMap;
}
/**
* needs to be called right after set as screen (should be called in show method).
* @param prefs
*/
public void loadShaders(Preferences prefs) {
if (prefs.getBoolean("glow shader")) {
Gdx.app.debug("Shader", "using glow shader");
glowShader = new ShaderProgram(Gdx.files.internal("shaders/glow.vsh"), Gdx.files.internal("shaders/glow.fsh"));
if (!glowShader.isCompiled()) {
System.err.println(glowShader.getLog());
System.exit(0);
}
if (glowShader.getLog().length() != 0) {
System.out.println(glowShader.getLog());
}
if (Gdx.graphics.getWidth() < 1024) {
fboSize = 1024;
} else if (Gdx.graphics.getWidth() < 2048) {
fboSize = 2048;
} else {
fboSize = 4096;
}
blurTarget = new FrameBuffer(Format.RGBA8888, fboSize, fboSize, false);
fboRegion = new TextureRegion(blurTarget.getColorBufferTexture());
fboRegion.flip(false, true);
}
ShaderProgram.pedantic = false;
}
@Override
public void draw() {
//TODO batch draw background
if (glowShader != null) {
blurTarget.begin();
Gdx.gl.glClearColor(0f, 0f, 0f, 0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
getBatch().setBlendFunction(-1, -1);
Gdx.gl20.glBlendFuncSeparate(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA,GL20.GL_ONE, GL20.GL_DST_ALPHA);
super.draw();
collisionDetector.renderParticles(getBatch(), Gdx.graphics.getDeltaTime(), true);
blurTarget.end(getViewport().getScreenX(), getViewport().getScreenY(), getViewport().getScreenWidth(), getViewport().getScreenHeight());
getBatch().setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
getBatch().setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
getBatch().begin();
getBatch().setShader(glowShader);
getBatch().draw(fboRegion, 0f, 0f, Main.GAME_AREA_WIDTH, Main.GAME_AREA_HEIGHT);
getBatch().setShader(null);
getBatch().end();
} else {
super.draw();
}
}
@Override
public void act(float delta) {
MapWindowData mwd;
if (audioMap != null && audioMap.getMusicData().getPlaybackMusic().isPlaying()) {
audioMap.getMusicData().readIndexUpdate();
if ((mwd = audioMap.getCurrentWindowBasedOnIndex()) != null) {
EntitySpawnInfo[] currentSpawnInfo = mwd.getArray();
if (currentSpawnInfo != null) {
for (int i = 0; i < currentSpawnInfo.length; i++) {
Entity entity = ec.getIndex().get(currentSpawnInfo[i].getEntityType()).buildEntity();
entity.init(currentSpawnInfo[i].parameters);
addActor(entity);
}
}
}
}
collisionDetector.collisionCheck();
if (polyjet.getX() <= 1) {
polyjet.moveLeft = false;
polyjet.setX(1f);
}
if (polyjet.getX() >= Main.GAME_AREA_WIDTH-1-polyjet.getWidth()) {
polyjet.moveRight = false;
polyjet.setX(Main.GAME_AREA_WIDTH-1f-polyjet.getWidth());
}
if (polyjet.getY() >= Main.GAME_AREA_HEIGHT - 1 - polyjet.getHeight()) {
polyjet.moveUp = false;
polyjet.setY(Main.GAME_AREA_HEIGHT - 1 - polyjet.getHeight());
}
if (polyjet.getY() <= 1) {
polyjet.moveDown = false;
polyjet.setY(1f);
}
super.act(delta);
}
public void addScore (int score) {
this.score += score;
polyjet.health += score;
if (polyjet.health > maxHealth) {
polyjet.health = maxHealth;
}
}
@Override
public boolean keyDown(int keycode) {
if (keycode == KeyMap.left) {
polyjet.moveLeft = true;
}
if (keycode == KeyMap.right) {
polyjet.moveRight = true;
}
if (keycode == KeyMap.up) {
polyjet.moveUp = true;
}
if (keycode == KeyMap.down) {
polyjet.moveDown = true;
}
if (keycode == KeyMap.accelerate) {
polyjet.accelerate = true;
}
return false;
}
@Override
public boolean keyUp(int keycode) {
if (keycode == KeyMap.left) {
polyjet.moveLeft = false;
}
if (keycode == KeyMap.right) {
polyjet.moveRight = false;
}
if (keycode == KeyMap.up) {
polyjet.moveUp = false;
}
if (keycode == KeyMap.down) {
polyjet.moveDown = false;
}
if (keycode == KeyMap.accelerate) {
polyjet.accelerate = false;
}
if (keycode == KeyMap.shoot) {
Laser laser = (Laser) ec.getIndex().get(EntityIndex.LASER).buildEntity();
laser.init(polyjet.getX() + polyjet.getWidth()/2f, polyjet.getY() + polyjet.getHeight()+1f, 60f);
addActor(laser);
}
return false;
}
public PolyJetEntity getPolyjet() {
return polyjet;
}
public int getScore() {
return score;
}
public int getMaxHealth() {
return maxHealth;
}
public float getyTeleport() {
return yTeleport;
}
@Override
public void dispose() {
if (glowShader != null) {
blurTarget.dispose();
glowShader.dispose();
}
super.dispose();
}
}

View File

@@ -0,0 +1,38 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.utils.FloatArray;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.ui.builders.AudioGraph;
public class BassUMGraphWindow extends Window {
AudioGraph graph;
AudioData audioData;
public BassUMGraphWindow(String title, Skin skin) {
super(title, skin, "tinted");
graph = new AudioGraph(300, 150);
add(graph);
pack();
}
@Override
public void act(float delta) {
if (audioData != null) {
graph.setAudioDataIndex(audioData.getReadIndex());
}
super.act(delta);
}
public AudioGraph getGraph() {
return graph;
}
public void setData(FloatArray dataSet1, FloatArray dataSet2, AudioData audioData) {
this.audioData = audioData;
graph.setGraphingData(dataSet1, dataSet2);
}
}

View File

@@ -0,0 +1,132 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.audio.AudioData;
public class BeatViewer extends Window {
Pixmap lights;
int songIndex;
AudioData music;
Texture lightOn;
private AudioAnalyzer data;
public BeatViewer(String title, Skin skin) {
super(title, skin, "tinted");
defaults().space(5f);
setSize(64, 100);
//Draw the 'lights'
lights = new Pixmap(16, 16, Format.RGBA8888);
lights.setColor(1, 0.2f, 0.2f, 1f);
lights.fillCircle(lights.getWidth()/2, lights.getHeight()/2, 7);
lightOn = new Texture(lights);
WidgetGroup bassBar = new WidgetGroup();
final Image bgBassBar = new Image(skin.getPatch("bar-empty"));
bgBassBar.setHeight(50f);
bassBar.setSize(bgBassBar.getWidth(), bgBassBar.getHeight());
final Image bassBarFill = new Image(skin.getPatch("bar-fill")) {
@Override
public void act(float delta) {
try {
if (music != null && data.getBassPeaks().get(songIndex) != 0) {
clearActions();
addAction(Actions.sequence(Actions.sizeTo(getWidth(), (data.getBassPeaks().get(songIndex)/data.getBassMaxValue())*bgBassBar.getHeight()), Actions.sizeTo(getWidth(), 0, 0.3f)));
}
} catch (IndexOutOfBoundsException e) {
}
super.act(delta);
}
};
bassBarFill.setHeight(0f);
bassBar.addActor(bgBassBar);
bassBar.addActor(bassBarFill);
add(bassBar).minSize(bassBar.getWidth(), bassBar.getHeight());
WidgetGroup UMBar = new WidgetGroup();
final Image bgUMBar = new Image(skin.getPatch("bar-empty"));
bgUMBar.setHeight(50f);
UMBar.setSize(bgUMBar.getWidth(), bgUMBar.getHeight());
Image UMBarFill = new Image(skin.getPatch("bar-fill")) {
@Override
public void act(float delta) {
try {
if (music != null && data.getUMPeaks().get(songIndex) != 0) {
clearActions();
addAction(Actions.sequence(Actions.sizeTo(getWidth(), (data.getUMPeaks().get(songIndex)/data.getUMMaxValue())*bgUMBar.getHeight()), Actions.sizeTo(getWidth(), 0f, 0.3f)));
}
} catch (IndexOutOfBoundsException e) {
}
super.act(delta);
}
};
UMBarFill.setHeight(0f);
UMBar.addActor(bgUMBar);
UMBar.addActor(UMBarFill);
add(UMBar).minSize(UMBar.getWidth(), UMBar.getHeight());
row();
Image bassIndicator = new Image(lightOn) {
@Override
public void act(float delta) {
try {
if (music != null && data.getBassPeaks().get(songIndex) != 0) {
clearActions();
addAction(Actions.sequence(Actions.alpha(1f), Actions.fadeOut(0.15f)));
}
} catch (IndexOutOfBoundsException e) {
}
super.act(delta);
}
};
bassIndicator.setColor(1f, 1f, 1f, 0f);
add(bassIndicator).center();
Image UMIndicator = new Image(lightOn) {
@Override
public void act(float delta) {
try {
if (music != null && data.getUMPeaks().get(songIndex) != 0) {
clearActions();
addAction(Actions.sequence(Actions.alpha(1f), Actions.fadeOut(0.15f)));
}
} catch (IndexOutOfBoundsException e) {
}
super.act(delta);
}
};
UMIndicator.setColor(1f, 1f, 1f, 0f);
add(UMIndicator).center();
}
@Override
public void act(float delta) {
if (music != null) {
songIndex = music.getReadIndex();
}
super.act(delta);
}
public void setMusic(AudioData audioData, AudioAnalyzer analyzer) {
this.music = audioData;
this.data = analyzer;
}
}

View File

@@ -0,0 +1,77 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
public class DifficultyWindow extends Window {
private Slider sensitivityRating;
private Label sensitivityRatingTitle;
private Slider speedModifier;
private Label speedModifierTitle;
private Slider healthModifier;
private Label healthModifierTitle;
public DifficultyWindow(Skin skin) {
super("Difficulty Adjuster", skin, "tinted");
sensitivityRating = new Slider(0f, 100f, 1f, false, skin);
sensitivityRating.setValue(0f);
sensitivityRating.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
sensitivityRatingTitle.setText("Base Difficulty: " + sensitivityRating.getValue());
}
});
sensitivityRatingTitle = new Label("Base Difficulty: " + sensitivityRating.getValue(), skin, "sub-font", skin.getColor("default"));
add(sensitivityRatingTitle);
add(sensitivityRating);
row();
speedModifier = new Slider(1f, 3f, 0.25f, false, skin);
speedModifier.setValue(1f);
speedModifier.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
speedModifierTitle.setText("Speed Modifier: " + speedModifier.getValue());
}
});
speedModifierTitle = new Label("Speed Modifier: " + speedModifier.getValue(), skin, "sub-font", skin.getColor("default"));
add(speedModifierTitle);
add(speedModifier);
row();
healthModifier = new Slider(0f, 5f, 1f, false, skin);
healthModifier.setValue(0f);
healthModifier.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
healthModifierTitle.setText("Health modifier: " + healthModifier.getValue());
}
});
healthModifierTitle = new Label("Health modifier: " + healthModifier.getValue(), skin, "sub-font", skin.getColor("default"));
add(healthModifierTitle);
add(healthModifier);
pack();
}
public float getSensitivityVal() {
return sensitivityRating.getValue();
}
public float getSpeedModifier() {
return speedModifier.getValue();
}
public float getHealthModifier() {
return healthModifier.getValue();
}
}

View File

@@ -0,0 +1,21 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
public class FPSWindow extends Window {
public FPSWindow(String title, Skin skin) {
super(title, skin, "tinted");
Label FPS = new Label("FPS: ", skin, "window-font", skin.getColor("default")) {
@Override
public void act(float delta) {
setText("FPS: " + Gdx.graphics.getFramesPerSecond());
super.act(delta);
}
};
add(FPS).center();
setSize(70, 70);
}
}

View File

@@ -0,0 +1,86 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.utils.Disposable;
public class LoadingWindow extends Window implements Disposable {
private Label status;
private Sound closeSound;
private Sound openSound;
private float vol;
public LoadingWindow(Skin skin, boolean progress, AssetManager assets, float vol) {
super("loading...", skin, "tinted");
this.openSound = assets.get("pop_open.ogg", Sound.class);
this.closeSound = assets.get("pop_close.ogg", Sound.class);
this.vol = vol;
Image loading = new Image(skin, "loading");
loading.addAction(Actions.forever(Actions.rotateBy(-360f, 2f)));
add(loading).left();
System.out.println(loading.getHeight());
setSize(loading.getWidth()+20f, loading.getHeight()+40f);
loading.setOrigin(loading.getWidth()/2, loading.getHeight()/2);
if (progress) {
status = new Label("[ ]", skin, "sub-font", skin.getColor("default"));
add(status).spaceLeft(10f).expandX().right();
setSize(getWidth() + status.getWidth() + 45f, (loading.getHeight() >= status.getHeight() ? loading.getHeight() : status.getHeight()) + 74);
}
}
public LoadingWindow(Skin skin, String styleName, boolean progress, AssetManager assets, float vol) {
super("loading...", skin, styleName);
this.openSound = assets.get("pop_open.ogg", Sound.class);
this.closeSound = assets.get("pop_close.ogg", Sound.class);
this.vol = vol;
Image loading = new Image(skin, "loading");
loading.addAction(Actions.forever(Actions.rotateBy(-360f, 2f)));
add(loading).left();
setSize(loading.getWidth()+20f, loading.getHeight()+40f);
loading.setOrigin(loading.getWidth()/2, loading.getHeight()/2);
if (progress) {
status = new Label("[ ]", skin, "sub-font", skin.getColor("default"));
add(status).spaceLeft(10f).expandX().right();
setSize(getWidth() + status.getWidth() + 45f, (loading.getHeight() >= status.getHeight() ? loading.getHeight() : status.getHeight()) + 74);
}
}
public void playOpenSound() {
openSound.play(vol/100f);
}
@Override
public boolean remove() {
closeSound.play(vol/100f);
return super.remove();
}
public void setProgress(float progress) {
status.setText(String.valueOf((int) progress) + '%');
}
@Override
public void dispose() {
openSound.dispose();
closeSound.dispose();
}
}

View File

@@ -0,0 +1,37 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.utils.FloatArray;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.ui.builders.AudioGraph;
public class MGraphWindow extends Window {
private AudioGraph graph;
private AudioData audioData;
public MGraphWindow(String title, Skin skin) {
super(title, skin, "tinted");
graph = new AudioGraph(300, 150);
add(graph);
pack();
}
@Override
public void act(float delta) {
if (audioData != null) {
graph.setAudioDataIndex(audioData.getReadIndex());
}
super.act(delta);
}
public AudioGraph getGraph() {
return graph;
}
public void setData(FloatArray dataSet1, FloatArray dataSet2, AudioData audioData) {
this.audioData = audioData;
graph.setGraphingData(dataSet1, dataSet2);
}
}

View File

@@ -0,0 +1,128 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import zero1hd.rhythmbullet.audio.AudioData;
public class MusicController extends Window {
Skin skin;
private Image togglePlay;
private TextField info;
private AudioData audiofile;
public MusicController(final Skin skin) {
super("Playback Controller", skin, "tinted");
defaults().space(5f);
this.skin = skin;
final ImageButton rewind = new ImageButton(skin.getDrawable("left-double-arrow"));
rewind.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (audiofile.getPlaybackMusic() != null) {
audiofile.getPlaybackMusic().setPosition(audiofile.getPlaybackMusic().getPosition() - 2);
info.setText(String.valueOf(MathUtils.round(audiofile.getPlaybackMusic().getPosition())) + " sec");
}
}
});
add(rewind).center();
togglePlay = new Image(skin.getDrawable("loading")) {
@Override
public void act(float delta) {
super.act(delta);
}
};
togglePlay.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
if (audiofile != null) {
if (audiofile.getPlaybackMusic().isPlaying()) {
audiofile.getPlaybackMusic().pause();
togglePlay.setDrawable(skin.getDrawable("arrow"));
} else {
togglePlay.setDrawable(skin.getDrawable("pause"));
audiofile.getPlaybackMusic().play();
}
}
super.clicked(event, x, y);
}
});
add(togglePlay).minWidth(togglePlay.getDrawable().getMinWidth()).center();
final ImageButton fastForward = new ImageButton(skin.getDrawable("right-double-arrow"));
fastForward.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (audiofile != null) {
audiofile.getPlaybackMusic().play();
audiofile.getPlaybackMusic().setPosition(audiofile.getPlaybackMusic().getPosition() + 2);
info.setText(String.valueOf(MathUtils.round(audiofile.getPlaybackMusic().getPosition())) + " sec");
}
}
});
add(fastForward);
info = new TextField(null, skin, "ui") {
@Override
public void act(float delta) {
if (audiofile != null && audiofile.getPlaybackMusic().isPlaying()) {
setText(String.valueOf(MathUtils.round(audiofile.getPlaybackMusic().getPosition())) + " sec");
}
super.act(delta);
}
};
add(info);
addListener(new InputListener() {
@Override
public boolean keyUp(InputEvent event, int keycode) {
if (keycode == Keys.ENTER) {
if (!info.getText().replaceAll("(?![0-9])\\S+", "").trim().isEmpty()) {
audiofile.getPlaybackMusic().setPosition(Float.valueOf(info.getText().replaceAll("(?![0-9])\\S+", "").trim()));
}
}
return super.keyUp(event, keycode);
}
});
setSize(260, 75);
}
public void setAudiofile(AudioData audiofile) {
this.audiofile = audiofile;
if (audiofile == null) {
togglePlay.setDrawable(skin.getDrawable("loading"));
info.setText("Analyzing...");
} else {
audiofile.reset();
togglePlay.setDrawable(skin.getDrawable("arrow"));
info.setText("Ready.");
audiofile.getPlaybackMusic().play();
audiofile.getPlaybackMusic().pause();
}
}
public AudioData getAudiofile() {
return audiofile;
}
}

View File

@@ -0,0 +1,105 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.List;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Array;
import zero1hd.rhythmbullet.audio.Audio;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniSender;
public class MusicSelector extends Window {
boolean confirmed;
boolean back;
FileHandle selectedMusic;
Array<String> fileNames;
private List<String> musicList;
private String path;
private ScrollPane listScroller;
public MiniSender miniSender;
public MusicSelector(String title, Skin skin, final String path, String listStyle) {
super(title, skin, "tinted");
this.path = path;
padTop(25f);
padLeft(5f);
padRight(5f);
miniSender = new MiniSender();
setSize(Gdx.graphics.getWidth()*0.5f, Gdx.graphics.getHeight()*0.5f);
fileNames = new Array<>();
musicList = new List<String>(skin, listStyle);
TextButton confirmButton = new TextButton("confirm", skin);
confirmButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
confirmed = true;
selectedMusic = Gdx.files.absolute(path+System.getProperty("file.separator")+musicList.getSelected());
miniSender.send(MiniEvents.MUSIC_SELECTED);
}
});
add(confirmButton);
TextButton regenMap = new TextButton("regen map", skin);
regenMap.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
miniSender.send(MiniEvents.MUSIC_DATA_CLEANED);
}
});
add(regenMap);
row();
listScroller = new ScrollPane(musicList, skin);
listScroller.setScrollingDisabled(true, false);
add(listScroller).colspan(2).expand().fill().prefWidth(getWidth()-5);
}
public void refresh() {
fileNames.clear();
FileHandle[] musicListArray = Gdx.files.absolute(path).list();
for (int i = 0; i < musicListArray.length; i++) {
if (musicListArray[i].name().toLowerCase().endsWith(".wav") || musicListArray[i].name().toLowerCase().endsWith(".mp3")) {
fileNames.add(musicListArray[i].name());
}
}
fileNames.sort();
musicList.setItems(fileNames);
}
public boolean isConfirmed() {
boolean isConfirmed = confirmed;
confirmed = false;
return isConfirmed;
}
public boolean isBack() {
boolean isBack = back;
back = false;
return isBack;
}
public AudioData getSelectedMusic() {
if (selectedMusic != null) {
return Audio.getAudioData(selectedMusic);
} else {
return null;
}
}
}

View File

@@ -0,0 +1,63 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Align;
public class NoticeWindow extends Window {
private Label noticeText;
private Skin skin;
private Sound closeSound;
private Sound openSound;
private float vol;
public NoticeWindow(Skin skin, String styleName, String text, float vol, AssetManager assets) {
super("Notice", skin, "tinted");
this.skin = skin;
this.openSound = assets.get("pop_open.ogg", Sound.class);
this.closeSound = assets.get("pop_close.ogg", Sound.class);
this.vol = vol;
noticeText = new Label(text, skin, "sub-font", skin.getColor("default"));
noticeText.setWrap(true);
noticeText.setAlignment(Align.center);
add(noticeText).expandX().fill().center().padLeft(20f).padRight(20f);
}
public NoticeWindow(Skin skin, String styleName, String title, String text, float vol, AssetManager assets) {
super(title, skin, styleName);
this.skin = skin;
this.openSound = assets.get("pop_open.ogg", Sound.class);
this.closeSound = assets.get("pop_close.ogg", Sound.class);
this.vol = vol;
noticeText = new Label(text, skin, "sub-font", skin.getColor("default"));
noticeText.setWrap(true);
noticeText.setAlignment(Align.center);
add(noticeText).expandX().fill().center().padLeft(20f).padRight(20f);
}
public void setupButton(String text, ChangeListener changeListener, int alignment) {
TextButton button = new TextButton(text, skin, "sub");
button.addListener(changeListener);
add(button).align(alignment);
}
public void playOpenSound() {
openSound.play(vol/100f);
}
@Override
public boolean remove() {
closeSound.play(vol/100f);
return super.remove();
}
}

View File

@@ -0,0 +1,31 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
public class PauseMenu extends Window {
private Label label;
private TextButton resumeButton;
public PauseMenu(Skin skin) {
super("Paused", skin, "tinted");
defaults().pad(25f);
label = new Label("Game is paused.", skin);
add(label).spaceBottom(15f);
row();
resumeButton = new TextButton("Resume", skin);
add(resumeButton);
pack();
setModal(true);
}
public TextButton getResumeButton() {
return resumeButton;
}
}

View File

@@ -0,0 +1,20 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
public class Spawnables extends Window {
public Spawnables(String title, Skin skin) {
super(title, skin, "tinted");
Table spawnButtons = new Table(skin);
ScrollPane entityListScroller = new ScrollPane(spawnButtons);
entityListScroller.setSize(180, 80);
add(entityListScroller);
setSize(185, 85);
}
}

View File

@@ -0,0 +1,108 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.List;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import zero1hd.rhythmbullet.entity.Entity;
import zero1hd.rhythmbullet.entity.EntityController;
import zero1hd.rhythmbullet.entity.EntityIndex;
import zero1hd.rhythmbullet.entity.ally.Laser;
import zero1hd.rhythmbullet.entity.enemies.Bar;
import zero1hd.rhythmbullet.entity.enemies.Flake;
import zero1hd.rhythmbullet.entity.enemies.Pellet;
import zero1hd.rhythmbullet.entity.enemies.Shard;
import zero1hd.rhythmbullet.entity.enemies.VoidCircle;
public class SpawnerWindow extends Window {
private EntityController ec;
private Stage stage;
private List<EntityIndex> listOfEntities;
private ScrollPane scroller;
private Slider mod1;
private Slider mod2;
private Slider mod3;
private Slider mod4;
public SpawnerWindow(String title, Skin skin, EntityController ec, Stage stageForEntities) {
super(title, skin, "tinted");
this.ec = ec;
stage = stageForEntities;
mod1 = new Slider(0.1f, 50f, 0.01f, true, skin);
mod2 = new Slider(0f, 15f, 0.01f, true, skin);
mod3 = new Slider(0.1f, 15f, 0.01f, true, skin);
mod4 = new Slider(1f, 12f, 0.01f, true, skin);
listOfEntities = new List<>(skin);
listOfEntities.setItems(EntityIndex.values());
scroller = new ScrollPane(listOfEntities);
add(scroller).expandY().fillY().spaceRight(15f);
add(mod1, mod2, mod3, mod4);
setSize(300f, 375f);
}
@Override
public boolean remove() {
return super.remove();
}
private Vector2 coords = new Vector2();
@Override
public void act(float delta) {
if (Gdx.input.justTouched() && Gdx.input.isKeyPressed(Keys.CONTROL_LEFT)) {
coords.set(Gdx.input.getX(), Gdx.input.getY());
stage.screenToStageCoordinates(coords);
Entity entity;
if ((entity = ec.getIndex().get(listOfEntities.getSelected()).buildEntity()) != null) {
switch(entity.getEntityType()) {
case LASER:
Laser laser = (Laser) entity;
laser.init(coords.x, coords.y, mod1.getValue());
stage.addActor(laser);
break;
case PELLET:
Pellet pellet = (Pellet) entity;
pellet.init(coords.x, coords.y, mod2.getValue()/mod2.getMaxValue()*360f, mod1.getValue());
stage.addActor(pellet);
break;
case VOID_CIRCLE:
VoidCircle voidCircle = (VoidCircle) entity;
voidCircle.init(mod2.getValue(), coords.x, coords.y, mod1.getValue(), mod3.getValue());
stage.addActor(voidCircle);
break;
case SHARD:
Shard shard = (Shard) entity;
shard.init(coords.x, coords.y, mod2.getValue()/mod2.getMaxValue()*360f, mod1.getValue(), (int) mod3.getValue());
stage.addActor(shard);
break;
case BAR:
Bar bar = (Bar) entity;
bar.init(coords.x, mod1.getValue());
stage.addActor(bar);
break;
case FLAKE:
Flake flake = (Flake) entity;
flake.init(coords.x, coords.y, mod1.getValue(), mod3.getValue(), mod2.getValue()/mod2.getMaxValue()*360f, (int) mod4.getValue());
stage.addActor(flake);
default:
break;
}
}
}
super.act(delta);
}
}

View File

@@ -0,0 +1,76 @@
package zero1hd.rhythmbullet.ui.windows;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.audio.AudioData;
public class VolumeWindow extends Window {
private Slider fxVolSlider;
private Slider musicVolSlider;
private Preferences prefs;
private AudioData music;
public VolumeWindow(String title, Skin skin, Preferences prefs) {
super(title, skin, "tinted");
this.prefs = prefs;
setSize(360f, 100f);
Label musicVolSliderLabel = new Label("Music Volume: ", skin, "window-font", skin.getColor("default"));
add(musicVolSliderLabel).left().padLeft(5f);
musicVolSlider = new Slider(0, 100, 0.1f, false, skin);
musicVolSlider.setValue(prefs.getFloat("music vol", 100f));
add(musicVolSlider).width(200f);
final Label musicVolPercentage = new Label(MathUtils.round(musicVolSlider.getValue()) + "%", skin, "window-font", skin.getColor("default"));
musicVolSlider.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
save();
musicVolPercentage.setText(MathUtils.round(musicVolSlider.getValue()) + "%");
if (music != null) {
music.getPlaybackMusic().setVolume(musicVolSlider.getValue()/100f);
}
}
});
add(musicVolPercentage).spaceLeft(10f).expandX().left();
row();
Label fxVolSliderLabel = new Label("FX Volume: ", skin, "window-font", skin.getColor("default"));
add(fxVolSliderLabel).left().padLeft(5f);
fxVolSlider = new Slider(0, 100, 1, false, skin);
fxVolSlider.setValue(prefs.getFloat("fx vol", 100f));
add(fxVolSlider).width(200f);
final Label fxVolPercentage = new Label(MathUtils.round(fxVolSlider.getValue()) + "%", skin, "window-font", skin.getColor("default"));
fxVolSlider.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
save();
fxVolPercentage.setText(MathUtils.round(fxVolSlider.getValue()) + "%");
}
});
add(fxVolPercentage).spaceLeft(10f).expandX().left();
}
public void save() {
prefs.putFloat("music vol", musicVolSlider.getValue());
prefs.putFloat("fx vol", fxVolSlider.getValue());
prefs.flush();
}
public void setMusic(AudioData music) {
this.music = music;
if (music != null) {
music.getPlaybackMusic().setVolume(prefs.getFloat("music vol")/100f);
}
}
}

View File

@@ -0,0 +1,49 @@
package zero1hd.rhythmbullet.util;
import java.util.HashMap;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Base64Coder;
import com.badlogic.gdx.utils.Json;
public class Base64Preferences {
FileHandle base64File;
HashMap<String, String> prefKeys;
Json json;
public Base64Preferences(String prefName) {
base64File = Gdx.files.external(".prefs/.priv/" + prefName);
json = new Json();
flush();
}
public void putString(String key, String string) {
prefKeys.put(key, string);
}
public void putObj(String key, Object object) {
prefKeys.put(key, json.toJson(object));
}
public void writeBase64String(String text) {
base64File.writeString(Base64Coder.encodeString(text), true);
}
public void writeBase64Object(Object obj) {
base64File.writeString(Base64Coder.encodeString(json.toJson(obj)), true);
}
@SuppressWarnings("unchecked")
public void flush() {
prefKeys = json.fromJson(HashMap.class, new String(Base64Coder.decode(base64File.readString())));
if (prefKeys == null) {
prefKeys = new HashMap<>();
}
base64File.writeString(null, false);
writeBase64Object(json);
}
}

View File

@@ -0,0 +1,25 @@
package zero1hd.rhythmbullet.util;
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
import com.badlogic.gdx.files.FileHandle;
public class GenericFileTypeHandler implements FileHandleResolver {
private final FileHandleResolver resolver;
public GenericFileTypeHandler(FileHandleResolver fileResolver) {
resolver = fileResolver;
}
@Override
public FileHandle resolve(String fileName) {
if (fileName.endsWith(".p")) {
return resolver.resolve("particles/" +fileName);
} else if (fileName.endsWith(".ogg")) {
return resolver.resolve("sounds/" + fileName);
} else {
return null;
}
}
}

View File

@@ -0,0 +1,5 @@
package zero1hd.rhythmbullet.util;
public enum MiniEvents {
SPECTRAL_FLUX_DONE, MUSIC_DATA_CLEANED, MUSIC_SELECTED, BACK, MAP_GENERATED, ANALYZER_ITERATED, MAPGEN_ITERATED;
}

View File

@@ -0,0 +1,5 @@
package zero1hd.rhythmbullet.util;
public interface MiniListener {
public void handle(MiniEvents ID);
}

View File

@@ -0,0 +1,25 @@
package zero1hd.rhythmbullet.util;
import com.badlogic.gdx.utils.Array;
public class MiniSender {
private Array<MiniListener> listeners;
public MiniSender() {
listeners = new Array<MiniListener>();
}
public void send(MiniEvents ID) {
for (MiniListener listener : listeners) {
listener.handle(ID);
}
}
public void addListener(MiniListener handler) {
listeners.add(handler);
}
public void removeListener(MiniListener listener) {
listeners.removeValue(listener, true);
}
}

View File

@@ -0,0 +1,65 @@
package zero1hd.rhythmbullet.util;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
import com.badlogic.gdx.assets.loaders.resolvers.ResolutionFileResolver.Resolution;
import com.badlogic.gdx.files.FileHandle;
public class RoundingResolutionHandler implements FileHandleResolver {
private final Resolution[] descriptors;
private final FileHandleResolver resolver;
public RoundingResolutionHandler(FileHandleResolver fileResolver, Resolution... descriptors) {
if (descriptors.length == 0) throw new IllegalArgumentException("At least one Resolution needs to be supplied.");
this.descriptors = descriptors;
this.resolver = fileResolver;
}
public Resolution chooseRounded(Resolution... descriptors) {
Resolution best = descriptors[0];
int leastDifference = -1;
int w = Gdx.graphics.getWidth(), h = Gdx.graphics.getHeight();
if (w > h) {
for (int i = 0; i < descriptors.length; i++) {
int currentDiff = h - descriptors[i].portraitHeight;
if (currentDiff < 0) {
currentDiff = currentDiff*-1;
}
if ((currentDiff < leastDifference) || leastDifference == -1) {
best = descriptors[i];
leastDifference = currentDiff;
}
}
} else {
for (int i = 0; i < descriptors.length; i++) {
int currentDiff = w - descriptors[i].portraitWidth;
if (currentDiff < 0) {
currentDiff = currentDiff*-1;
}
if (currentDiff < leastDifference || leastDifference == -1) {
best = descriptors[i];
leastDifference = currentDiff;
}
}
}
return best;
}
@Override
public FileHandle resolve(String fileName) {
Gdx.app.debug("RResolution Handler", "Finding best match for resolution: " + Gdx.graphics.getWidth() + "x" + Gdx.graphics.getHeight() + " for file: " + fileName);
Resolution bestRes = chooseRounded(descriptors);
Gdx.app.debug("RResolution Handler", "Selected folder: " + bestRes.folder);
FileHandle resSpecificFile = resolver.resolve(bestRes.folder + "/" + fileName);
if (!resSpecificFile.exists()) resSpecificFile = resolver.resolve(fileName);
return resSpecificFile;
}
}

View File

@@ -0,0 +1,7 @@
package zero1hd.rhythmbullet.util;
import com.badlogic.gdx.Screen;
public interface TransitionAdapter {
public Screen postTransition();
}