diff --git a/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java b/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java index 1109bdf..3e5c481 100755 --- a/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java +++ b/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java @@ -50,7 +50,7 @@ public class AudioAnalyzer { int PUID; boolean work; private volatile int progress; - private float secondsPerFrame; + private float secondsPerWindow; public AudioAnalyzer() { sender = new MiniSender(); @@ -190,7 +190,7 @@ public class AudioAnalyzer { } Gdx.app.debug("Audio Analyzer", "Data prunned."); - secondsPerFrame = audioData.getReadWindowSize()/audioData.getFormat().getSampleRate(); + secondsPerWindow = audioData.getReadWindowSize()/audioData.getFormat().getSampleRate(); //peak detection int lastID = 0; @@ -225,7 +225,7 @@ public class AudioAnalyzer { } //then we minus one from the beats so it actually works out avgBPS -= UMPrunned.size-lastID; - avgBPS *= secondsPerFrame; + avgBPS *= secondsPerWindow; avgBPS = beats/avgBPS; } @@ -266,9 +266,9 @@ public class AudioAnalyzer { analyticalThread.start(); } - public void runThresholdCleaning(float baseThresholdMultiplier, float UMThresholdMultiplier) { - this.bassThresholdMultiplier = baseThresholdMultiplier; - this.UMThresholdMultiplier = UMThresholdMultiplier; + public void runThresholdCleaning(float rangeModifier) { + this.bassThresholdMultiplier += rangeModifier; + this.UMThresholdMultiplier += rangeModifier; work = true; Thread thresholdClean = new Thread(thresholdCalculator); thresholdClean.start(); @@ -339,7 +339,7 @@ public class AudioAnalyzer { return avgBPS; } - public float getsecondsPerFrame() { - return secondsPerFrame; + public float getsecondsPerWindow() { + return secondsPerWindow; } } diff --git a/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java b/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java index 1364130..54efda0 100755 --- a/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java +++ b/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java @@ -16,15 +16,23 @@ public class RhythmMapAlgorithm implements Runnable { private MersenneTwister rand; private GamePlayMap map; private float avgBPS; - private float second; - public RhythmMapAlgorithm(AudioAnalyzer analyzer) { + + private float speedMod, healthMod; + + private float windowPerSecond; + + private volatile int progress; + public RhythmMapAlgorithm(AudioAnalyzer analyzer, float speedMod, float healthMod) { bassPeaks = analyzer.getBassPeaks(); UMPeaks = analyzer.getUMPeaks(); overlappedPeaks = analyzer.getOverlappedPeaks(); map = new GamePlayMap(analyzer.getAudioData()); rand = new MersenneTwister(analyzer.getPUID()); avgBPS = analyzer.getAvgBPS(); - second = analyzer.getsecondsPerFrame(); + windowPerSecond = 1/analyzer.getsecondsPerWindow(); + + this.speedMod = speedMod; + this.healthMod = healthMod; } @Override @@ -32,22 +40,23 @@ public class RhythmMapAlgorithm implements Runnable { map.beginBuild(); for (int index = 0; index < bassPeaks.size; index++) { if (bassPeaks.get(index) != 0 || UMPeaks.get(index) != 0) { - if (overlappedPeaks.get(index+3) != 0) { + int warningTime = (int) ((3/speedMod)*windowPerSecond); + if (overlappedPeaks.get(index + warningTime) != 0) { //TODO basic void circle spawning - float endRadius = rand.nextFloat()*Polyjet.GAME_AREA_WIDTH; + float endRadius = overlappedPeaks.get(index+3)*Polyjet.GAME_AREA_WIDTH; map.addToMap(Entities.VOID_CIRCLE, endRadius, rand.nextFloat()*Polyjet.GAME_AREA_WIDTH, rand.nextFloat()*Polyjet.GAME_AREA_HEIGHT, - avgBPS, - 3f*second + endRadius/avgBPS, + warningTime ); } if (bassPeaks.get(index) != 0) { map.addToMap(Entities.BAR, MathUtils.round(rand.nextFloat()*Polyjet.GAME_AREA_WIDTH), - bassPeaks.get(index)*Polyjet.GAME_AREA_HEIGHT/avgBPS); + ((Polyjet.GAME_AREA_HEIGHT-bassPeaks.get(index)*Polyjet.GAME_AREA_HEIGHT)/avgBPS)*speedMod); } else { if (UMPeaks.get(index) != 0) { //TODO basic pellet scatter spawn @@ -57,6 +66,8 @@ public class RhythmMapAlgorithm implements Runnable { } else { map.addRestToMap(); } + + progress = (int) (100f*index/bassPeaks.size); } map.endBuild(); } @@ -64,4 +75,8 @@ public class RhythmMapAlgorithm implements Runnable { public synchronized GamePlayMap getMap() { return map; } + + public synchronized int getProgress() { + return progress; + } } diff --git a/core/src/zero1hd/polyjet/screens/PreGameScreen.java b/core/src/zero1hd/polyjet/screens/PreGameScreen.java index ad05cf2..68bc6b1 100755 --- a/core/src/zero1hd/polyjet/screens/PreGameScreen.java +++ b/core/src/zero1hd/polyjet/screens/PreGameScreen.java @@ -4,10 +4,8 @@ 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.graphics.Texture; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.scenes.scene2d.Stage; -import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.utils.viewport.ScreenViewport; import zero1hd.polyjet.Polyjet; @@ -80,12 +78,6 @@ public class PreGameScreen extends ScreenAdapter implements TransitionAdapter, M @Override public Screen postTransition() { - Image circle1 = new Image(core.getAssetManager().get("cybercircle1.png", Texture.class)); - circle1.setOrigin(circle1.getWidth()/2f, circle1.getHeight()/2f); - circle1.setPosition(Gdx.graphics.getWidth(), circle1.getHeight()/3); - stage.addActor(circle1); - - ms = new MusicSelectionPage(core); ms.miniSender.addListener(this); ms.beginMusicSearch(); diff --git a/core/src/zero1hd/polyjet/ui/pages/AnalyzePage.java b/core/src/zero1hd/polyjet/ui/pages/AnalyzePage.java index 3123787..01721af 100755 --- a/core/src/zero1hd/polyjet/ui/pages/AnalyzePage.java +++ b/core/src/zero1hd/polyjet/ui/pages/AnalyzePage.java @@ -1,5 +1,6 @@ package zero1hd.polyjet.ui.pages; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; @@ -18,6 +19,7 @@ import com.badlogic.gdx.utils.Align; import zero1hd.polyjet.audio.AudioAnalyzer; import zero1hd.polyjet.audio.AudioData; import zero1hd.polyjet.audio.AudioInfo; +import zero1hd.polyjet.audio.map.RhythmMapAlgorithm; import zero1hd.polyjet.ui.builders.ScrollText; import zero1hd.polyjet.util.MiniEvents; import zero1hd.polyjet.util.MiniListener; @@ -25,6 +27,7 @@ import zero1hd.polyjet.util.MiniListener; public class AnalyzePage extends Page implements MiniListener { AudioAnalyzer audioAnalyzer; AudioData music; + RhythmMapAlgorithm mapGenAlgorithm; Table difficultyTable; private Label diffTitle; @@ -34,6 +37,8 @@ public class AnalyzePage extends Page implements MiniListener { private Label speedModifierTitle; private Slider healthModifier; private Label healthModifierTitle; + private TextButton confirmDiffButton; + private boolean confirmed; private Skin skin; private TextButton back; @@ -42,22 +47,100 @@ public class AnalyzePage extends Page implements MiniListener { Table songInfo; private Label[] info; + private Thread mapGenThread; public AnalyzePage(Skin skin, AssetManager assets) { super("Results", skin); this.skin = skin; + difficultyTable = new Table(skin); - //TODO work on sliders and stuff + difficultyTable.setBackground(skin.getDrawable("large-pane")); + addActor(difficultyTable); + + diffTitle = new Label("Difficulty", skin); + difficultyTable.add(diffTitle).expandX().left(); + + difficultyTable.row(); + + sensitivityRating = new Slider(-5f, 5f, 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")); + 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: " + speedModifier.getValue()); + if (audioAnalyzer.containsData()) { + audioAnalyzer.runThresholdCleaning(sensitivityRating.getValue()); + } + } + }); + speedModifierTitle = new Label("Speed Modifier: " + 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(); + + 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); + if (audioAnalyzer.containsData()) { + finalizeData(); + } + } + }); + difficultyTable.add(confirmDiffButton); + + difficultyTable.pack(); songInfo = new Table(skin); songInfo.setBackground(skin.getDrawable("large-pane")); - + addActor(songInfo); + loadingCircle = new Image(assets.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()); @@ -75,7 +158,6 @@ public class AnalyzePage extends Page implements MiniListener { } addActor(back); - addActor(songInfo); } public void setSong(AudioData music, AudioInfo audioInfo, MiniListener listener) { @@ -101,10 +183,11 @@ public class AnalyzePage extends Page implements MiniListener { 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()); + startTime = System.currentTimeMillis(); info[0].addAction(Actions.color(Color.BLACK, 2.5f)); - System.out.println(songInfo); } @@ -130,7 +213,11 @@ public class AnalyzePage extends Page implements MiniListener { switch (ID) { case ANALYZER_ITERATED: if (audioAnalyzer.getProgress() == 50) { - songInfo.addAction(Actions.moveTo(40f, getHeightBelowTitle()-songInfo.getHeight()-25f, 0.75f, Interpolation.linear)); + 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; @@ -138,10 +225,32 @@ public class AnalyzePage extends Page implements MiniListener { 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()); + mapGenThread = new Thread(mapGenAlgorithm); + mapGenThread.start(); + break; + case MAPGEN_ITERATED: + info[4].setText("Generating map: " + mapGenAlgorithm.getProgress()); default: break; } } + + private void finalizeData() { + Gdx.app.debug("analyze", "confirmed data finalization."); + audioAnalyzer.runThresholdCleaning(sensitivityRating.getValue()); + info[3].setText("finalizing data..."); + info[3].addAction(Actions.color(Color.BLACK, 0.75f)); + } + + private void generateMap() { + + } } diff --git a/core/src/zero1hd/polyjet/util/MiniEvents.java b/core/src/zero1hd/polyjet/util/MiniEvents.java index c50b380..c5ebaa7 100755 --- a/core/src/zero1hd/polyjet/util/MiniEvents.java +++ b/core/src/zero1hd/polyjet/util/MiniEvents.java @@ -1,5 +1,5 @@ package zero1hd.polyjet.util; public enum MiniEvents { - SPECTRAL_FLUX_DONE, MUSIC_DATA_CLEANED, MUSIC_SELECTED, BACK, MAP_GENERATED, ANALYZER_ITERATED; + SPECTRAL_FLUX_DONE, MUSIC_DATA_CLEANED, MUSIC_SELECTED, BACK, MAP_GENERATED, ANALYZER_ITERATED, MAPGEN_ITERATED; }