added more environment controls, improved audio-data calculation

This commit is contained in:
Raybz@Raybz 2013-06-14 10:55:02 +02:00
parent a877d9758d
commit 1ce11d8197
10 changed files with 350 additions and 54 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

View File

@ -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() {

View File

@ -0,0 +1,78 @@
/*
* Copyright (C) 2013 Darth Affe <http://wyrez.org> 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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@ -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);

View File

@ -0,0 +1,89 @@
/*
* Copyright (C) 2013 Darth Affe <http://wyrez.org> 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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@ -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;

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2013 Darth Affe <http://wyrez.org> 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 <http://www.gnu.org/licenses/>.
*/
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));
}
}

View File

@ -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);

View File

@ -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;
}
}