diff --git a/ShootingStars/assets/Textures/Hex.jpg b/ShootingStars/assets/Textures/Hex.jpg deleted file mode 100644 index 53c1cf3..0000000 Binary files a/ShootingStars/assets/Textures/Hex.jpg and /dev/null differ diff --git a/ShootingStars/assets/Textures/Hex.png b/ShootingStars/assets/Textures/Hex.png new file mode 100644 index 0000000..3cf27f4 Binary files /dev/null and b/ShootingStars/assets/Textures/Hex.png differ diff --git a/ShootingStars/src/org/wyrez/shootingstars/audiodata/AudioDataManager.java b/ShootingStars/src/org/wyrez/shootingstars/audiodata/AudioDataManager.java index a2b4e78..3ff1ed8 100644 --- a/ShootingStars/src/org/wyrez/shootingstars/audiodata/AudioDataManager.java +++ b/ShootingStars/src/org/wyrez/shootingstars/audiodata/AudioDataManager.java @@ -22,6 +22,7 @@ import org.wyrez.audio.util.Band; import org.wyrez.audio.util.SampleBuffer; import org.wyrez.audio.util.SampleHelper; import org.wyrez.shootingstars.game.GameSettings; +import org.wyrez.shootingstars.states.GameState; import uk.co.caprica.vlcj.player.MediaPlayer; /** @@ -33,7 +34,7 @@ public class AudioDataManager { private static final int MIN_PEAK_DIFF = 13; //~198.8bpm private static final Band LOW_BAND = new Band(1f, 140); private static final Band MID_BAND = new Band(400f, 1200f); - private static final Band HIGH_BAND = new Band(4000f, 8000f); + private static final Band HIGH_BAND = new Band(4000f, 16000f); /**/ private AudioProcessor audioProcessorLowBand; private AudioProcessor audioProcessorMidBand; @@ -42,9 +43,10 @@ public class AudioDataManager { private int bufferSize; private float samplingRate; private float[] speedData; - private float[] movementData; +// private float[] movementData; private float[] flashData; - private float peakAverage; + private float[] groundMoveData; + private float peakAverageFlash; private float indexFactor; private float bpm; private float currentTime; @@ -84,13 +86,15 @@ public class AudioDataManager { speedData = calcWave(audioProcessorLowBand.getSpectrum(), 4, 24, 3); SampleHelper.normalize(speedData, 0f, 1f); - movementData = calcWave(audioProcessorLowBand.getPeaks(), 2, 4, 16); - SampleHelper.normalize(movementData, 0f, 1f); + + //TODO if there is some time left... +// movementData = calcWave(audioProcessorLowBand.getPeaks(), 2, 2, 48); +// SampleHelper.normalize(movementData, 0f, 1f); audioProcessorLowBand.cutFastPeaks(MIN_PEAK_DIFF); - flashData = audioProcessorLowBand.getPeaks(); - peakAverage = audioProcessorLowBand.getPeakAverage(); + groundMoveData = audioProcessorLowBand.getPeaks(); + SampleHelper.normalize(groundMoveData, 0f, 1f); bpm = audioProcessorLowBand.getBpm(); while (bpm > 200f) { @@ -101,6 +105,18 @@ public class AudioDataManager { audioProcessorLowBand = null; } + private float calculateAverage(float[] data) { + int counter = 0; + float sum = 0f; + for (int i = 0; i < data.length; i++) { + if (data[i] > 0f) { + sum += data[i]; + counter++; + } + } + return sum / counter; + } + public void analyseMidBand() { audioProcessorMidBand.calculate(); audioProcessorMidBand.cutFastPeaks(MIN_PEAK_DIFF); @@ -112,6 +128,16 @@ public class AudioDataManager { public void analyseHighBand() { audioProcessorHighBand.calculate(); + flashData = audioProcessorHighBand.getPeaks(); + float maxValue = audioProcessorHighBand.getPeakAverage() * 2f; + for (int i = 0; i < flashData.length; i++) { + if (flashData[i] > maxValue) { + flashData[i] = maxValue; + } + } + SampleHelper.normalize(flashData, 0f, 1f); + peakAverageFlash = calculateAverage(audioProcessorHighBand.getPeaks()); + audioProcessorHighBand.clean(); audioProcessorHighBand = null; } @@ -148,21 +174,32 @@ public class AudioDataManager { private int calcIndex() { int index = (int) (currentTime * indexFactor); - if (index > flashData.length) { - index = flashData.length - 1; + if (index >= speedData.length) { + index = speedData.length - 1; } return index; } public boolean isFlash() { - return flashData[calcIndex()] > peakAverage * 0.5f; + return flashData[calcIndex()] > peakAverageFlash * 0.5f; + } + + public float getFlashData() { + return flashData[calcIndex()]; + } + + public boolean isGroundMove() { + return groundMoveData[calcIndex()] > 0f; + } + + public float getGroundMoveData() { + return groundMoveData[calcIndex()]; } public float getMovementData() { - return 0.5f; - //TODO argf - //System.out.println(currentTime + " * " + indexFactor + " = " + calcIndex() + " --> " + movementData[calcIndex()]); - //return movementData[calcIndex()]; + return 0.25f; +// System.out.println(currentTime + " * " + indexFactor + " = " + calcIndex() + " --> " + movementData[calcIndex()]); +// return movementData[calcIndex()]; } public float getSpeedData() { diff --git a/ShootingStars/src/org/wyrez/shootingstars/controls/GroundBorderGlowControl.java b/ShootingStars/src/org/wyrez/shootingstars/controls/GroundBorderGlowControl.java new file mode 100644 index 0000000..2e1315f --- /dev/null +++ b/ShootingStars/src/org/wyrez/shootingstars/controls/GroundBorderGlowControl.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2013 Darth Affe and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.wyrez.shootingstars.controls; + +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.scene.Geometry; +import com.jme3.scene.Spatial; +import com.jme3.scene.control.Control; +import org.wyrez.shootingstars.audiodata.AudioDataManager; + +/** + * + * @author Darth Affe + */ +public class GroundBorderGlowControl extends BaseControl { + + private static final float GLOW_DURATION = 0.25f; + /**/ + private AudioDataManager audioDataManager; + private Material material; + private float glowTimer = 0; + private boolean reset = false; + + public GroundBorderGlowControl(AudioDataManager audioDataManager) { + this.audioDataManager = audioDataManager; + } + + @Override + public void setSpatial(Spatial spatial) { + super.setSpatial(spatial); + this.material = ((Geometry) spatial).getMaterial(); + this.material.setColor("GlowColor", ColorRGBA.Black); + } + + @Override + public void update(float tpf) { + if (audioDataManager.isGroundMove()) { + glowTimer = GLOW_DURATION; + reset = true; + } + + if (glowTimer > 0f) { + float glowFactor = (glowTimer / GLOW_DURATION); + if (glowFactor > 0.5f) { + glowFactor = 1f; + } else { + glowFactor += 0.5f; + } + float glowValue = (0.75f + (audioDataManager.getGroundMoveData() * 0.25f)) * glowFactor; + material.setColor("GlowColor", new ColorRGBA(glowValue, glowValue, glowValue, 1f)); + glowTimer -= tpf; + } else if (reset) { + material.setColor("GlowColor", ColorRGBA.Black); + reset = false; + } + } + + public Control cloneForSpatial(Spatial spatial) { + GroundBorderGlowControl control = new GroundBorderGlowControl(audioDataManager); + control.setSpatial(spatial); + return control; + } +} diff --git a/ShootingStars/src/org/wyrez/shootingstars/controls/GroundGlowControl.java b/ShootingStars/src/org/wyrez/shootingstars/controls/GroundGlowControl.java index 04a0acb..e79746b 100644 --- a/ShootingStars/src/org/wyrez/shootingstars/controls/GroundGlowControl.java +++ b/ShootingStars/src/org/wyrez/shootingstars/controls/GroundGlowControl.java @@ -21,6 +21,7 @@ import com.jme3.math.ColorRGBA; import com.jme3.scene.Geometry; import com.jme3.scene.Spatial; import com.jme3.scene.control.Control; +import java.util.Random; import org.wyrez.shootingstars.audiodata.AudioDataManager; /** @@ -29,11 +30,13 @@ import org.wyrez.shootingstars.audiodata.AudioDataManager; */ public class GroundGlowControl extends BaseControl { + private static final Random random = new Random(); private static final float GLOW_DURATION = 0.33f; /**/ private AudioDataManager audioDataManager; private Material material; private float glowTimer = 0; + private ColorRGBA color; public GroundGlowControl(AudioDataManager audioDataManager) { this.audioDataManager = audioDataManager; @@ -48,8 +51,11 @@ public class GroundGlowControl extends BaseControl { @Override public void update(float tpf) { - if (audioDataManager.isFlash()) { - glowTimer = GLOW_DURATION; + if (audioDataManager.isFlash() && glowTimer <= 0f) { + if (random.nextBoolean()) { + glowTimer = GLOW_DURATION; + color = calcColor(audioDataManager.getFlashData()); + } } if (glowTimer > 0f) { @@ -59,12 +65,34 @@ public class GroundGlowControl extends BaseControl { } else { glowFactor += 0.5f; } - material.setColor("GlowColor", new ColorRGBA(1f * glowFactor, - 1f * glowFactor, 1f * glowFactor, 1f)); + material.setColor("GlowColor", new ColorRGBA(color.r * glowFactor, + color.b * glowFactor, color.g * glowFactor, 1f)); glowTimer -= tpf; } } + private ColorRGBA calcColor(float value) { + int r, g, b; + if (value < 0.25f) { + r = 0; + g = Math.round(255 * value / 0.25f); + b = 255; + } else if (value < 0.5f) { + r = 0; + g = 255; + b = Math.round(255 * ((0.25f - (value - 0.25f)) / 0.25f)); + } else if (value < 0.75f) { + g = 255; + r = Math.round(255 * (value - 0.5f) / 0.25f); + b = 0; + } else { + g = Math.round(255 * ((0.25f - (value - 0.75f)) / 0.25f)); + r = 255; + b = 0; + } + return new ColorRGBA((float) r / 255f, (float) g / 255f, (float) b / 255f, 1f); + } + public Control cloneForSpatial(Spatial spatial) { GroundGlowControl control = new GroundGlowControl(audioDataManager); control.setSpatial(spatial); diff --git a/ShootingStars/src/org/wyrez/shootingstars/controls/GroundMoveControl.java b/ShootingStars/src/org/wyrez/shootingstars/controls/GroundMoveControl.java new file mode 100644 index 0000000..c05d1bb --- /dev/null +++ b/ShootingStars/src/org/wyrez/shootingstars/controls/GroundMoveControl.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2013 Darth Affe and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.wyrez.shootingstars.controls; + +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import com.jme3.scene.control.Control; +import java.util.Random; +import org.wyrez.shootingstars.audiodata.AudioDataManager; + +/** + * + * @author Darth Affe + */ +public class GroundMoveControl extends BaseControl { + + private static final Random random = new Random(); + private static final float MOVE_UP_DURATION = 0.15f; + private static final float MOVE_DOWN_DURATION = 0.3f; + private static final float MOVE_DURATION = MOVE_UP_DURATION + MOVE_DOWN_DURATION; + /**/ + private AudioDataManager audioDataManager; + private float moveTimer = 0; + private float internalTimer = 0; + private Vector3f basePosition; + private float moveHeight; + + public GroundMoveControl(AudioDataManager audioDataManager) { + this.audioDataManager = audioDataManager; + } + + @Override + public void setSpatial(Spatial spatial) { + super.setSpatial(spatial); + basePosition = new Vector3f(spatial.getLocalTranslation()); + } + + @Override + public void update(float tpf) { + if (audioDataManager.isGroundMove() && moveTimer <= 0f) { + if (random.nextBoolean()) { + moveTimer = MOVE_UP_DURATION + MOVE_DOWN_DURATION; + internalTimer = 0f; + moveHeight = 300f * audioDataManager.getGroundMoveData() + * (0.5f + random.nextFloat() * 0.5f); + } + } + + if (moveTimer > 0f) { + if (moveTimer < MOVE_DURATION - MOVE_UP_DURATION) { + float moveFactor = 1f - ((internalTimer - MOVE_UP_DURATION) / MOVE_DOWN_DURATION); + spatial.setLocalTranslation(basePosition.getX(), + basePosition.getY() + moveHeight * moveFactor, basePosition.getZ()); + moveTimer -= tpf; + internalTimer += tpf; + } else { + float moveFactor = (internalTimer / MOVE_UP_DURATION); + spatial.setLocalTranslation(basePosition.getX(), + basePosition.getY() + moveHeight * moveFactor, basePosition.getZ()); + moveTimer -= tpf; + internalTimer += tpf; + } + } else if (internalTimer > 0f) { + spatial.setLocalTranslation(basePosition.getX(), + basePosition.getY(), basePosition.getZ()); + internalTimer = 0f; + } + } + + public Control cloneForSpatial(Spatial spatial) { + GroundMoveControl control = new GroundMoveControl(audioDataManager); + control.setSpatial(spatial); + return control; + } +} diff --git a/ShootingStars/src/org/wyrez/shootingstars/factories/Materials.java b/ShootingStars/src/org/wyrez/shootingstars/factories/Materials.java index d5d4d7d..9e4b3fe 100644 --- a/ShootingStars/src/org/wyrez/shootingstars/factories/Materials.java +++ b/ShootingStars/src/org/wyrez/shootingstars/factories/Materials.java @@ -26,7 +26,8 @@ import com.jme3.material.Material; public enum Materials { UNSHADED("Common/MatDefs/Misc/Unshaded.j3md", null), - HEX("Common/MatDefs/Light/Lighting.j3md", "Textures/Hex.jpg"); + HEX("Common/MatDefs/Light/Lighting.j3md", "Textures/Hex.png"), + GLOW("Common/MatDefs/Light/Lighting.j3md", null); private static AssetManager assetManager; private String material; private String texture; diff --git a/ShootingStars/src/org/wyrez/shootingstars/game/GlowingHexPrism.java b/ShootingStars/src/org/wyrez/shootingstars/game/GlowingHexPrism.java new file mode 100644 index 0000000..8284f40 --- /dev/null +++ b/ShootingStars/src/org/wyrez/shootingstars/game/GlowingHexPrism.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2013 Darth Affe and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.wyrez.shootingstars.game; + +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.Node; +import org.wyrez.shootingstars.audiodata.AudioDataManager; +import org.wyrez.shootingstars.controls.GroundGlowControl; +import org.wyrez.shootingstars.factories.Materials; +import org.wyrez.shootingstars.mesh.HexPrism; + +/** + * + * @author Darth Affe + */ +public class GlowingHexPrism extends Node { + + private Geometry prism; + private Geometry glow; + + public GlowingHexPrism(Vector3f position, float size, float height, + float glowPercentage, AudioDataManager adm) { + super("HexPrism " + position); + + Material prismMat = Materials.HEX.create(); + prismMat.setColor("Diffuse", ColorRGBA.Black); + prism = new Geometry("Prism " + position, new HexPrism(position, size, height)); + prism.setMaterial(prismMat); + this.attachChild(prism); + + Material glowMat = Materials.GLOW.create(); + glowMat.setColor("Diffuse", ColorRGBA.White); + glow = new Geometry("Prism " + position, new HexPrism(position.add( + 0f, height, 0f), size * glowPercentage, height * 0.001f)); + glow.setMaterial(glowMat); + this.attachChild(glow); + + glow.addControl(new GroundGlowControl(adm)); + } +} diff --git a/ShootingStars/src/org/wyrez/shootingstars/game/Ground.java b/ShootingStars/src/org/wyrez/shootingstars/game/Ground.java index fcc8d14..b89cf9a 100644 --- a/ShootingStars/src/org/wyrez/shootingstars/game/Ground.java +++ b/ShootingStars/src/org/wyrez/shootingstars/game/Ground.java @@ -17,12 +17,15 @@ package org.wyrez.shootingstars.game; import com.jme3.light.AmbientLight; -import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.math.FastMath; import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; import com.jme3.scene.Node; +import org.wyrez.shootingstars.audiodata.AudioDataManager; +import org.wyrez.shootingstars.controls.GroundBorderGlowControl; +import org.wyrez.shootingstars.controls.GroundGlowControl; +import org.wyrez.shootingstars.controls.GroundMoveControl; import org.wyrez.shootingstars.factories.Materials; import org.wyrez.shootingstars.mesh.HexPrism; @@ -31,32 +34,30 @@ import org.wyrez.shootingstars.mesh.HexPrism; * @author Darth Affe */ public class Ground extends Node { - - public Ground() { - this(1000f); + + public Ground(AudioDataManager adm) { + this(adm, 1000f); } - - public Ground(float radius) { - this(radius, 0.1f); + + public Ground(AudioDataManager adm, float radius) { + this(adm, radius, 0.1f); } - - public Ground(float radius, float factor) { + + public Ground(AudioDataManager adm, float radius, float factor) { super("Ground"); - generateHexGrid(radius, factor); + generateHexGrid(adm, radius, factor); addLight(); } //TODO cleanup - private void generateHexGrid(float borderWidth, float factor) { + private void generateHexGrid(AudioDataManager adm, float borderWidth, float factor) { float size = borderWidth * factor; int maxIterations = (int) (borderWidth / size) - 2; - - Material mat = Materials.HEX.create(); - Geometry geom = new Geometry("HexPrism" + 0 + " - " + 0, - new HexPrism(new Vector3f(0f, 0f, 0f), size, 10f)); - geom.setMaterial(mat); - this.attachChild(geom); - + + Node prism = new GlowingHexPrism(new Vector3f(0f, -140f, 0f), size, 150f, 0.8f, adm); + prism.addControl(new GroundMoveControl(adm)); + this.attachChild(prism); + float xcc = 0f; float ycc = 0f; float centerDistance = size * FastMath.sqrt(3f); @@ -65,14 +66,21 @@ public class Ground extends Node { float yc = ycc - (float) iteration * centerDistance; float dx = (FastMath.sqrt(3f) * centerDistance / 2f); float dy = centerDistance / 2f; - + for (int directions = 0; directions < 6; directions++) { for (int steps = 0; steps < iteration; steps++) { - geom = new Geometry("HexPrism" + xc + " - " + yc, - new HexPrism(new Vector3f(xc, 0f, yc), size, - (iteration == maxIterations - 1) ? 160f : 10f)); - geom.setMaterial(mat); - this.attachChild(geom); + if ((iteration == maxIterations - 1)) { + Geometry hex = new Geometry("Prism_" + xc + " - " + yc, + new HexPrism(new Vector3f(xc, 0f, yc), size, 160f)); + hex.setMaterial(Materials.HEX.create()); + hex.addControl(new GroundBorderGlowControl(adm)); + this.attachChild(hex); + } else { + prism = new GlowingHexPrism(new Vector3f(xc, -140f, yc), size, + 150f, 0.8f, adm); + prism.addControl(new GroundMoveControl(adm)); + this.attachChild(prism); + } xc = xc + dx; yc = yc + dy; } @@ -83,7 +91,7 @@ public class Ground extends Node { } } } - + private void addLight() { AmbientLight ambient = new AmbientLight(); ambient.setColor(ColorRGBA.White); diff --git a/ShootingStars/src/org/wyrez/shootingstars/states/GameState.java b/ShootingStars/src/org/wyrez/shootingstars/states/GameState.java index 80bbf40..ce7ce96 100644 --- a/ShootingStars/src/org/wyrez/shootingstars/states/GameState.java +++ b/ShootingStars/src/org/wyrez/shootingstars/states/GameState.java @@ -30,10 +30,7 @@ import com.jme3.scene.Geometry; import com.jme3.scene.Node; import com.jme3.scene.Spatial; import com.jme3.scene.shape.Box; -import com.jme3.texture.Image; -import org.wyrez.audio.decoder.DecoderFactory; import org.wyrez.shootingstars.audiodata.AudioDataManager; -import org.wyrez.shootingstars.controls.GroundGlowControl; import org.wyrez.shootingstars.controls.PlayerCamControl; import org.wyrez.shootingstars.controls.PlayerMouseControl; import org.wyrez.shootingstars.controls.PlayerMoveControl; @@ -93,12 +90,7 @@ public class GameState extends AbstractAppState implements GameListener { } public void loadGround() { - ground = new Ground(); - -// for (Spatial s : ground.getChildren()) { -// s.addControl(new GroundGlowControl(audioDataManager)); -// } - + ground = new Ground(audioDataManager); FilterPostProcessor fpp = new FilterPostProcessor(assetManager); fpp.addFilter(new BloomFilter(BloomFilter.GlowMode.Objects)); viewPort.addProcessor(fpp); @@ -168,7 +160,9 @@ public class GameState extends AbstractAppState implements GameListener { @Override public void update(float tpf) { - audioDataManager.update(tpf); + if (isRunning) { + audioDataManager.update(tpf); + } } @Override @@ -185,4 +179,8 @@ public class GameState extends AbstractAppState implements GameListener { public DirectMediaPlayer getMediaPlayer() { return mediaPlayer; } + + public boolean isRunning() { + return isRunning; + } }