Testmerge #5
@@ -1,4 +1,166 @@
|
|||||||
package pp.mdga.client.Acoustic;
|
package pp.mdga.client.Acoustic;
|
||||||
|
|
||||||
|
import com.jme3.audio.AudioNode;
|
||||||
|
import com.jme3.system.NanoTimer;
|
||||||
|
import pp.mdga.client.MdgaApp;
|
||||||
|
import pp.mdga.client.MdgaState;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
public class AcousticHandler {
|
public class AcousticHandler {
|
||||||
|
private MdgaApp app;
|
||||||
|
|
||||||
|
private MdgaState state = MdgaState.NONE;
|
||||||
|
|
||||||
|
boolean playGame = false;
|
||||||
|
private ArrayList<MusicAsset> gameTracks = new ArrayList<>();
|
||||||
|
private Random random = new Random();
|
||||||
|
private NanoTimer trackTimer = new NanoTimer();
|
||||||
|
|
||||||
|
private boolean fading = false;
|
||||||
|
private boolean crossFading = false;
|
||||||
|
private GameMusic scheduled = null;
|
||||||
|
private GameMusic playing = null;
|
||||||
|
private NanoTimer fadeTimer = new NanoTimer();
|
||||||
|
private float fadeVolume = 1.0f;
|
||||||
|
private final float FADE_DURATION = 3.0f; // Sekunden für das Fading
|
||||||
|
private final float CROSSFADE_DURATION = 1.0f; // Zeit, in der beide Tracks gleichzeitig spielen
|
||||||
|
|
||||||
|
private float mainVolume = 1.0f;
|
||||||
|
private float musicVolume = 1.0f;
|
||||||
|
private float soundVolume = 1.0f;
|
||||||
|
|
||||||
|
public AcousticHandler(MdgaApp app) {
|
||||||
|
this.app = app;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMainVolume() {
|
||||||
|
return mainVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMusicVolume() {
|
||||||
|
return musicVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getSoundVolume() {
|
||||||
|
return soundVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
updateVolumeAndTrack();
|
||||||
|
|
||||||
|
if(playGame) {
|
||||||
|
updateGameTracks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void playState(MdgaState state) {
|
||||||
|
if(this.state == state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MusicAsset asset = null;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case MAIN:
|
||||||
|
playGame = false;
|
||||||
|
asset = MusicAsset.MAIN_MENU;
|
||||||
|
break;
|
||||||
|
case LOBBY:
|
||||||
|
playGame = false;
|
||||||
|
asset = MusicAsset.LOBBY;
|
||||||
|
break;
|
||||||
|
case GAME:
|
||||||
|
addGameTracks();
|
||||||
|
playGame = true;
|
||||||
|
asset = gameTracks.remove(0);
|
||||||
|
break;
|
||||||
|
case CEREMONY:
|
||||||
|
playGame = false;
|
||||||
|
asset = MusicAsset.CEREMONY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(null != asset) : "music sceduling went wrong";
|
||||||
|
|
||||||
|
scheduled = new GameMusic(app, asset.getPath(), getMusicVolume() * getMainVolume(), asset.getLoop());
|
||||||
|
}
|
||||||
|
|
||||||
|
private float lerp(float start, float end, float t) {
|
||||||
|
return start + t * (end - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateVolumeAndTrack() {
|
||||||
|
if (playing == null && scheduled != null && !fading) {
|
||||||
|
playing = scheduled;
|
||||||
|
scheduled = null;
|
||||||
|
fadeVolume = 1.0f;
|
||||||
|
playing.play();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scheduled != null && !fading) {
|
||||||
|
fading = true;
|
||||||
|
fadeTimer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fading) {
|
||||||
|
float time = fadeTimer.getTimeInSeconds();
|
||||||
|
|
||||||
|
if (time <= FADE_DURATION) {
|
||||||
|
float t = Math.min(time / FADE_DURATION, 1.0f);
|
||||||
|
float oldVolume = lerp(1.0f, 0.0f, t);
|
||||||
|
if (playing != null) {
|
||||||
|
playing.update(getMusicVolume() * getMainVolume() * oldVolume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time > FADE_DURATION && time <= FADE_DURATION + CROSSFADE_DURATION) {
|
||||||
|
float t = Math.min((time - FADE_DURATION) / CROSSFADE_DURATION, 1.0f);
|
||||||
|
float newVolume = lerp(0.0f, 1.0f, t);
|
||||||
|
|
||||||
|
if (!scheduled.isPlaying()) {
|
||||||
|
scheduled.play();
|
||||||
|
}
|
||||||
|
scheduled.update(getMusicVolume() * getMainVolume() * newVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time > FADE_DURATION + CROSSFADE_DURATION) {
|
||||||
|
if (playing != null) {
|
||||||
|
playing.pause();
|
||||||
|
}
|
||||||
|
playing = scheduled;
|
||||||
|
scheduled = null;
|
||||||
|
|
||||||
|
fadeVolume = 1.0f;
|
||||||
|
fading = false;
|
||||||
|
}
|
||||||
|
} else if (playing != null) {
|
||||||
|
playing.update(getMusicVolume() * getMainVolume());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addGameTracks() {
|
||||||
|
for (int i = 1; i <= 6; i++) {
|
||||||
|
gameTracks.add(MusicAsset.valueOf("GAME_" + i));
|
||||||
|
}
|
||||||
|
Collections.shuffle(gameTracks, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateGameTracks() {
|
||||||
|
if (playing != null && playing.nearEnd(3) && trackTimer.getTimeInSeconds() > 20) {
|
||||||
|
trackTimer.reset();
|
||||||
|
|
||||||
|
if (gameTracks.isEmpty()) {
|
||||||
|
addGameTracks();
|
||||||
|
}
|
||||||
|
|
||||||
|
MusicAsset nextTrack = gameTracks.remove(0);
|
||||||
|
|
||||||
|
scheduled = new GameMusic(app, nextTrack.getPath(), getMusicVolume() * getMainVolume(), nextTrack.getLoop());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package pp.mdga.client.Acoustic;
|
||||||
|
|
||||||
|
import com.jme3.audio.AudioData;
|
||||||
|
import com.jme3.audio.AudioNode;
|
||||||
|
import com.jme3.audio.AudioSource;
|
||||||
|
import pp.mdga.client.MdgaApp;
|
||||||
|
|
||||||
|
public class GameMusic {
|
||||||
|
private final MdgaApp app;
|
||||||
|
|
||||||
|
private float volume;
|
||||||
|
private AudioNode music;
|
||||||
|
|
||||||
|
GameMusic(MdgaApp app, String path, float volume, boolean loop) {
|
||||||
|
this.app = app;
|
||||||
|
this.volume = volume;
|
||||||
|
|
||||||
|
loadMusic(path);
|
||||||
|
|
||||||
|
music.setLooping(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void play() {
|
||||||
|
if(null == music) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
music.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pause() {
|
||||||
|
if(null == music) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
music.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
if(null == music) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
music.setTimeOffset(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isPlaying() {
|
||||||
|
return music.getStatus() == AudioSource.Status.Playing;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean nearEnd(float thresholdSeconds) {
|
||||||
|
if (music == null || !isPlaying()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float currentTime = music.getPlaybackTime(); // Current playback time in seconds
|
||||||
|
float duration = music.getAudioData().getDuration(); // Total duration in seconds
|
||||||
|
|
||||||
|
if (duration <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float remainingTime = duration - currentTime;
|
||||||
|
|
||||||
|
return remainingTime <= thresholdSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(float newVolume) {
|
||||||
|
if(volume != newVolume) {
|
||||||
|
volume = newVolume;
|
||||||
|
music.setVolume(volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadMusic(String path) {
|
||||||
|
music = new AudioNode(app.getAssetManager(), path, AudioData.DataType.Stream);
|
||||||
|
music.setVolume(volume);
|
||||||
|
music.setPositional(false);
|
||||||
|
music.setDirectional(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package pp.mdga.client.Acoustic;
|
||||||
|
|
||||||
|
public class GameSound {
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package pp.mdga.client.Acoustic;
|
||||||
|
|
||||||
|
public enum MusicAsset {
|
||||||
|
MAIN_MENU("Spaceship.wav"),
|
||||||
|
LOBBY("DeadPlanet.wav"),
|
||||||
|
CEREMONY("80s,Disco,Life.wav"),
|
||||||
|
GAME_1("NeonRoadTrip.wav", false),
|
||||||
|
GAME_2("NoPressureTrance.wav", false),
|
||||||
|
GAME_3("TheSynthRave.wav", false),
|
||||||
|
GAME_4("LaserParty.wav", false),
|
||||||
|
GAME_5("RetroNoir.wav", false),
|
||||||
|
GAME_6("SpaceInvaders.wav", false);
|
||||||
|
|
||||||
|
private final String path;
|
||||||
|
private final boolean loop;
|
||||||
|
|
||||||
|
MusicAsset(String name) {
|
||||||
|
this.path = "music/" + name;
|
||||||
|
this.loop = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MusicAsset(String name, boolean loop) {
|
||||||
|
this.path = "music/" + name;
|
||||||
|
this.loop = loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getLoop() { return loop; }
|
||||||
|
}
|
||||||
@@ -23,8 +23,9 @@ public class BoardView {
|
|||||||
private ArrayList<PieceControl> pieces;
|
private ArrayList<PieceControl> pieces;
|
||||||
|
|
||||||
public BoardView(int playerCount, MdgaApp mdgaApp) {
|
public BoardView(int playerCount, MdgaApp mdgaApp) {
|
||||||
assert(2 <= playerCount && playerCount <= 4);
|
assert(2 <= playerCount && playerCount <= 4) : "invalid player count";
|
||||||
assert(mdgaApp != null);
|
assert(mdgaApp != null) : "app is null";
|
||||||
|
|
||||||
|
|
||||||
this.mdgaApp = mdgaApp;
|
this.mdgaApp = mdgaApp;
|
||||||
|
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ public List<AssetOnMap> loadMap(String mapName) {
|
|||||||
if(entry.charAt(0) == '#') continue;
|
if(entry.charAt(0) == '#') continue;
|
||||||
|
|
||||||
String[] parts = entry.trim().split(" ");
|
String[] parts = entry.trim().split(" ");
|
||||||
if(parts.length != 2) throw new RuntimeException();
|
assert(parts.length == 2) : "parts.lenghth != 2";
|
||||||
|
|
||||||
String assetName = parts[0];
|
String assetName = parts[0];
|
||||||
String[] coordinates = parts[1].split(",");
|
String[] coordinates = parts[1].split(",");
|
||||||
|
|
||||||
if(coordinates.length != 2) throw new RuntimeException();
|
assert(coordinates.length == 2) : "coordinates.lenghth != 2";
|
||||||
|
|
||||||
int x = Integer.parseInt(coordinates[0]);
|
int x = Integer.parseInt(coordinates[0]);
|
||||||
int y = Integer.parseInt(coordinates[1]);
|
int y = Integer.parseInt(coordinates[1]);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package pp.mdga.client;
|
package pp.mdga.client;
|
||||||
|
|
||||||
import com.jme3.app.SimpleApplication;
|
import com.jme3.app.SimpleApplication;
|
||||||
|
import com.jme3.system.NanoTimer;
|
||||||
|
import pp.mdga.client.Acoustic.AcousticHandler;
|
||||||
import pp.mdga.client.Animation.AnimationHandler;
|
import pp.mdga.client.Animation.AnimationHandler;
|
||||||
import com.jme3.light.AmbientLight;
|
import com.jme3.light.AmbientLight;
|
||||||
import com.jme3.light.DirectionalLight;
|
import com.jme3.light.DirectionalLight;
|
||||||
@@ -20,15 +22,20 @@
|
|||||||
|
|
||||||
public class MdgaApp extends SimpleApplication {
|
public class MdgaApp extends SimpleApplication {
|
||||||
private AnimationHandler animationHandler;
|
private AnimationHandler animationHandler;
|
||||||
|
private AcousticHandler acousticHandler;
|
||||||
private BoardView boardView;
|
private BoardView boardView;
|
||||||
|
|
||||||
|
NanoTimer test = new NanoTimer();
|
||||||
|
private MdgaState testState = MdgaState.MAIN;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
MdgaApp app = new MdgaApp();
|
|
||||||
AppSettings settings = new AppSettings(true);
|
AppSettings settings = new AppSettings(true);
|
||||||
settings.setSamples(128);
|
settings.setSamples(128);
|
||||||
settings.setCenterWindow(true);
|
settings.setCenterWindow(true);
|
||||||
settings.setWidth(1300);
|
settings.setWidth(1280);
|
||||||
settings.setHeight(1000);
|
settings.setHeight(720);
|
||||||
|
|
||||||
|
MdgaApp app = new MdgaApp();
|
||||||
app.setSettings(settings);
|
app.setSettings(settings);
|
||||||
app.setShowSettings(false);
|
app.setShowSettings(false);
|
||||||
app.start();
|
app.start();
|
||||||
@@ -37,8 +44,11 @@ public static void main(String[] args) {
|
|||||||
@Override
|
@Override
|
||||||
public void simpleInitApp() {
|
public void simpleInitApp() {
|
||||||
animationHandler = new AnimationHandler(this);
|
animationHandler = new AnimationHandler(this);
|
||||||
|
acousticHandler = new AcousticHandler(this);
|
||||||
boardView = new BoardView(4,this);
|
boardView = new BoardView(4,this);
|
||||||
|
|
||||||
|
acousticHandler.playState(MdgaState.GAME);
|
||||||
|
|
||||||
flyCam.setEnabled(true);
|
flyCam.setEnabled(true);
|
||||||
int zoom = 20;
|
int zoom = 20;
|
||||||
cam.setLocation(new Vector3f(zoom,0,zoom));
|
cam.setLocation(new Vector3f(zoom,0,zoom));
|
||||||
@@ -48,6 +58,7 @@ public void simpleInitApp() {
|
|||||||
sun.setColor(ColorRGBA.White);
|
sun.setColor(ColorRGBA.White);
|
||||||
sun.setDirection(new Vector3f(-1,0,-1));
|
sun.setDirection(new Vector3f(-1,0,-1));
|
||||||
rootNode.addLight(sun);
|
rootNode.addLight(sun);
|
||||||
|
|
||||||
AmbientLight ambient = new AmbientLight();
|
AmbientLight ambient = new AmbientLight();
|
||||||
ambient.setColor(new ColorRGBA(0.3f,0.3f,0.3f,1));
|
ambient.setColor(new ColorRGBA(0.3f,0.3f,0.3f,1));
|
||||||
rootNode.addLight(ambient);
|
rootNode.addLight(ambient);
|
||||||
@@ -56,12 +67,39 @@ public void simpleInitApp() {
|
|||||||
DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(assetManager, SHADOWMAP_SIZE, 4);
|
DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(assetManager, SHADOWMAP_SIZE, 4);
|
||||||
dlsr.setLight(sun);
|
dlsr.setLight(sun);
|
||||||
viewPort.addProcessor(dlsr);
|
viewPort.addProcessor(dlsr);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void simpleUpdate(float tpf) {
|
public void simpleUpdate(float tpf) {
|
||||||
//this method will be called every game tick and can be used to make updates
|
acousticHandler.update();
|
||||||
|
|
||||||
|
test.reset();
|
||||||
|
if(test.getTimeInSeconds() > 10){
|
||||||
|
if(testState == MdgaState.MAIN) {
|
||||||
|
testState = MdgaState.LOBBY;
|
||||||
|
acousticHandler.playState(MdgaState.MAIN);
|
||||||
|
} else if (testState == MdgaState.LOBBY) {
|
||||||
|
testState = MdgaState.CEREMONY;
|
||||||
|
acousticHandler.playState(MdgaState.LOBBY);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
testState = MdgaState.MAIN;
|
||||||
|
acousticHandler.playState(MdgaState.CEREMONY);
|
||||||
|
}
|
||||||
|
|
||||||
|
test.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnimationHandler getAnimationHandler() {
|
||||||
|
return animationHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AcousticHandler getAcousticHandler() {
|
||||||
|
return acousticHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoardView getBoardView() {
|
||||||
|
return boardView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,12 @@
|
|||||||
import pp.mdga.notification.PlayerInGameNotification;
|
import pp.mdga.notification.PlayerInGameNotification;
|
||||||
|
|
||||||
public enum MdgaState {
|
public enum MdgaState {
|
||||||
|
NONE {
|
||||||
|
@Override
|
||||||
|
void handleNotification(MdgaApp app, Notification notification) {
|
||||||
|
throw new RuntimeException("unexpected notification");
|
||||||
|
}
|
||||||
|
},
|
||||||
MAIN {
|
MAIN {
|
||||||
@Override
|
@Override
|
||||||
void handleNotification(MdgaApp app, Notification notification) {
|
void handleNotification(MdgaApp app, Notification notification) {
|
||||||
|
|||||||
Reference in New Issue
Block a user