diff --git a/Projekte/.run/MdgaApp.run.xml b/Projekte/.run/MdgaApp.run.xml index abb487c3..051df2ea 100644 --- a/Projekte/.run/MdgaApp.run.xml +++ b/Projekte/.run/MdgaApp.run.xml @@ -2,7 +2,7 @@ - \ No newline at end of file + diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/AcousticHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/AcousticHandler.java new file mode 100644 index 00000000..0e436b03 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/AcousticHandler.java @@ -0,0 +1,290 @@ +package pp.mdga.client.Acoustic; + +import com.jme3.system.NanoTimer; +import pp.mdga.client.MdgaApp; +import pp.mdga.client.MdgaState; + +import java.util.*; + +public class AcousticHandler { + private MdgaApp app; + + private MdgaState state = MdgaState.NONE; + + private boolean playGame = false; + private ArrayList gameTracks = new ArrayList<>(); + private NanoTimer trackTimer = new NanoTimer(); + + private boolean fading = false; + private NanoTimer fadeTimer = new NanoTimer(); + private final float FADE_DURATION = 3.0f; + private final float CROSSFADE_DURATION = 1.5f; + + private float mainVolume = 1.0f; + private float musicVolume = 1.0f; + private float soundVolume = 1.0f; + + private GameMusic scheduled = null; + private GameMusic playing = null; + private ArrayList sounds = new ArrayList<>(); + + public AcousticHandler(MdgaApp app) { + this.app = app; + } + + /** + * This method updates the acousticHandler and should be called every frame + */ + public void update() { + updateVolumeAndTrack(); + + if(playGame) { + updateGameTracks(); + } + + Iterator iterator = sounds.iterator(); + while (iterator.hasNext()) { + GameSound s = iterator.next(); + + s.update(getSoundVolumeTotal()); + + if (!s.isPlaying()) { + iterator.remove(); + } + } + } + + /** + * This method instantly plays a sound + * + * @param sound the sound to be played + */ + public void playSound(MdgaSound sound) { + ArrayList assets = new ArrayList(); + switch (sound) { + case LOST: + assets.add(new SoundAssetDelayVolume(SoundAsset.LOST, 1.0f, 0.0f)); + break; + case VICTORY: + assets.add(new SoundAssetDelayVolume(SoundAsset.VICTORY, 1.0f, 2.0f)); + break; + default: + + break; + } + + for (SoundAssetDelayVolume sawd : assets) { + GameSound gameSound = new GameSound(app, sawd.asset(), getSoundVolumeTotal(), sawd.subVolume(), sawd.delay()); + sounds.add(gameSound); + } + } + + /** + * This method fades the played music to fit the state. + * + * @param state the state of which the corresponding music should be played to be played + */ + 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; + assert(gameTracks.size() > 0) : "no more game music available"; + 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, getMusicVolumeTotal(), asset.getSubVolume(), asset.getLoop()); + } + + /** + * Performs linear interpolation between two float values. + * + * @param start The starting value. + * @param end The ending value. + * @param t The interpolation factor, typically between 0 and 1. + * @return The interpolated value between start and end. + */ + private float lerp(float start, float end, float t) { + return start + t * (end - start); + } + + /** + * Updates the current volume and handles track crossfading logic. + * This method is responsible for fading out the currently playing track, + * fading in the scheduled track, and handling crossfade between the two tracks. + */ + private void updateVolumeAndTrack() { + if (playing == null && scheduled != null && !fading) { + playing = scheduled; + scheduled = null; + 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(getMusicVolumeTotal()* 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(getMusicVolumeTotal() * newVolume); + } + + if (time > FADE_DURATION + CROSSFADE_DURATION) { + if (playing != null) { + playing.pause(); + } + playing = scheduled; + scheduled = null; + + fading = false; + } + } else if (playing != null) { + playing.update(getMusicVolumeTotal()); + } + } + + /** + * Adds a list of game tracks to the gameTracks collection and shuffles them. + * This method adds predefined game tracks to the track list and shuffles the order. + */ + private void addGameTracks() { + Random random = new Random(); + + for (int i = 1; i <= 6; i++) { + gameTracks.add(MusicAsset.valueOf("GAME_" + i)); + } + Collections.shuffle(gameTracks, random); + } + + /** + * Updates the current game tracks. If the currently playing track is nearing its end, + * a new track will be scheduled to play. If the list of game tracks is empty, it will be refreshed. + */ + private void updateGameTracks() { + if(playing.nearEnd(10)) { + if (gameTracks.isEmpty()) { + addGameTracks(); + } + } + + if (playing != null && playing.nearEnd(3) && trackTimer.getTimeInSeconds() > 20) { + trackTimer.reset(); + + MusicAsset nextTrack = gameTracks.remove(0); + + scheduled = new GameMusic(app, nextTrack, getMusicVolumeTotal(), nextTrack.getSubVolume(), nextTrack.getLoop()); + } + } + + /** + * Retrieves the main volume level. + * + * @return The current main volume level. + */ + public float getMainVolume() { + return mainVolume; + } + + /** + * Retrieves the music volume level. + * + * @return The current music volume level. + */ + public float getMusicVolume() { + return musicVolume; + } + + /** + * Retrieves the sound volume level. + * + * @return The current sound volume level. + */ + public float getSoundVolume() { + return soundVolume; + } + + /** + * Sets the main volume level. + * + * @param mainVolume The desired main volume level. + */ + public void setMainVolume(float mainVolume) { + this.mainVolume = mainVolume; + } + + /** + * Sets the music volume level. + * + * @param musicVolume The desired music volume level. + */ + public void setMusicVolume(float musicVolume) { + this.musicVolume = musicVolume; + } + + /** + * Sets the sound volume level. + * + * @param soundVolume The desired sound volume level. + */ + public void setSoundVolume(float soundVolume) { + this.soundVolume = soundVolume; + } + + /** + * Calculates the total music volume by multiplying the music volume by the main volume. + * + * @return The total music volume. + */ + float getMusicVolumeTotal() { + + return getMusicVolume() * getMainVolume(); + } + + /** + * Calculates the total sound volume by multiplying the sound volume by the main volume. + * + * @return The total sound volume. + */ + float getSoundVolumeTotal() { + return getSoundVolume() * getMainVolume(); + } +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/GameMusic.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/GameMusic.java new file mode 100644 index 00000000..7345de66 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/GameMusic.java @@ -0,0 +1,110 @@ +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; + +/** + * Represents a game music track, including its playback controls and volume settings. + * This class manages the playback of a music track, allowing for playing, pausing, + * volume adjustment, and tracking the current status of the music. + */ +class GameMusic { + private float volume; + private final float subVolume; + private final AudioNode music; + + /** + * Constructs a new GameMusic object. + * + * @param app The instance of the application, used to access the asset manager. + * @param asset The music asset to be played. + * @param volume The total volume of the music, adjusted by the main volume. + * @param subVolume A relative volume that modifies the base music volume, typically a percentage. + * @param loop A flag indicating whether the music should loop once it finishes. + */ + GameMusic(MdgaApp app, MusicAsset asset, float volume, float subVolume, boolean loop) { + this.volume = volume; + this.subVolume = subVolume; + + music = new AudioNode(app.getAssetManager(), asset.getPath(), AudioData.DataType.Stream); + music.setPositional(false); + music.setDirectional(false); + music.setVolume(volume * subVolume); + + music.setLooping(loop); + } + + /** + * Plays the current music track. + * If the music is already initialized, it starts playback. + * If the music is not available, no action is performed. + */ + void play() { + if(null == music) { + return; + } + + music.play(); + } + + /** + * Pauses the current music track. + * If the music is not available or is not playing, no action is performed. + */ + void pause() { + if(null == music) { + return; + } + + music.stop(); + } + + /** + * Checks if the current music track is playing. + * + * @return true if the music is playing, false otherwise. + */ + boolean isPlaying() { + + return music.getStatus() == AudioSource.Status.Playing; + } + + /** + * Checks if the current music track is near the end. + * + * @param thresholdSeconds The threshold in seconds. If the remaining time is less than or equal to this value, + * the track is considered near the end. + * @return true if the track is near its end (within the threshold), false otherwise. + */ + 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; + } + + /** + * Updates the volume of the music. + * If the volume has changed, it will adjust the music's volume accordingly. + * + * @param newVolume The new total volume for the music. + */ + void update(float newVolume) { + if(volume != newVolume) { + volume = newVolume; + music.setVolume(volume * subVolume); + } + } +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/GameSound.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/GameSound.java new file mode 100644 index 00000000..9f01a365 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/GameSound.java @@ -0,0 +1,83 @@ +package pp.mdga.client.Acoustic; + +import com.jme3.audio.AudioData; +import com.jme3.audio.AudioNode; +import com.jme3.audio.AudioSource; +import com.jme3.system.NanoTimer; +import pp.mdga.client.MdgaApp; + +/** + * Represents a game sound effect, with control over playback, volume, and timing. + * This class manages the playback of a sound effect, including starting playback after a delay, + * adjusting volume, and tracking whether the sound has finished playing. + */ +class GameSound { + private float volume; + final private float subVolume; + + private final AudioNode sound; + + private boolean playing = false; + private boolean finished = false; + + private float delay = 0.0f; + private NanoTimer timer = null; + + /** + * Constructs a new GameSound object. + * + * @param app The instance of the application, used to access the asset manager. + * @param asset The sound asset to be played. + * @param volume The total volume of the sound, adjusted by the main volume. + * @param subVolume A relative volume that modifies the base sound volume, typically a percentage. + * @param delay The delay before the sound starts playing, in seconds. + */ + GameSound(MdgaApp app, SoundAsset asset, float volume, float subVolume, float delay) { + this.volume = volume; + this.subVolume = subVolume; + this.delay = delay; + + sound = new AudioNode(app.getAssetManager(), asset.getPath(), AudioData.DataType.Buffer); + sound.setPositional(false); + sound.setDirectional(false); + sound.setLooping(false); + sound.setVolume(volume * subVolume); + + timer = new NanoTimer(); + } + + /** + * Checks if the sound is currently playing. + * + * @return true if the sound is playing, false otherwise. + */ + boolean isPlaying() { + return !finished; + } + + /** + * Updates the sound playback, adjusting the volume if necessary, and starting + * the sound after the specified delay. + * + * @param newVolume The new total volume for the sound. + */ + void update(float newVolume) { + if(!playing && timer.getTimeInSeconds() > delay) { + sound.play(); + playing = true; + } + + if(!playing) { + return; + } + + if(volume != newVolume) { + volume = newVolume; + sound.setVolume(volume * subVolume); + } + + if(sound != null && sound.getStatus() == AudioSource.Status.Playing) { + finished = true; + } + } +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/MdgaSound.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/MdgaSound.java new file mode 100644 index 00000000..651208b6 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/MdgaSound.java @@ -0,0 +1,23 @@ +package pp.mdga.client.Acoustic; + +/** + * Enum representing the various sound effects used in the game. + * Each sound corresponds to an event or action in the game and may consist of one or more + * audio files, potentially with time delays between them. + * + * These sounds are used to play specific audio cues, such as when a dice is rolled, + * a turn starts or ends, a piece is moved or lost, and various other events in the game. + */ +public enum MdgaSound { + DICE_ROLL, + TURN_START, + TURN_END, + PIECE_END, + PIECE_MOVE, + PIECE_LOST, + SELECT, + DESELECT, + HURRY, + VICTORY, + LOST; +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/MusicAsset.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/MusicAsset.java new file mode 100644 index 00000000..70018f66 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/MusicAsset.java @@ -0,0 +1,76 @@ +package pp.mdga.client.Acoustic; + +/** + * Enum representing various music assets used in the game. + * Each constant corresponds to a specific music track, along with its properties such as file path, + * looping behavior, and relative volume (subVolume). + * These music assets are used to control the music that plays in different parts of the game, such as menus and in-game music. + */ +enum MusicAsset { + MAIN_MENU("Spaceship.wav", 1.0f), + LOBBY("DeadPlanet.wav", 1.0f), + CEREMONY("80s,Disco,Life.wav", 1.0f), + GAME_1("NeonRoadTrip.wav", false, 1.0f), + GAME_2("NoPressureTrance.wav", false, 1.0f), + GAME_3("TheSynthRave.wav", false, 1.0f), + GAME_4("LaserParty.wav", false, 1.0f), + GAME_5("RetroNoir.wav", false, 1.0f), + GAME_6("SpaceInvaders.wav", false, 1.0f); + + private final String path; + private final boolean loop; + private final float subVolume; + + /** + * Constructs a new MusicAsset object with the specified name and sub-volume. + * The track will not loop by default. + * + * @param name The name of the music file. + * @param subVolume A relative volume that modifies the base volume of the track (typically a percentage). + */ + MusicAsset(String name, float subVolume) { + this.path = "music/" + name; + this.loop = false; + this.subVolume = subVolume; + } + + /** + * Constructs a new MusicAsset object with the specified name, loop flag, and sub-volume. + * + * @param name The name of the music file. + * @param loop If true, the track will loop; otherwise, it will play once. + * @param subVolume A relative volume that modifies the base volume of the track (typically a percentage). + */ + MusicAsset(String name, boolean loop, float subVolume) { + this.path = "music/" + name; + this.loop = loop; + this.subVolume = subVolume; + } + + /** + * Gets the file path of the music track. + * + * @return The path to the music file (relative to the music folder). + */ + public String getPath() { + return path; + } + + /** + * Gets whether the music track should loop. + * + * @return true if the track should loop, false otherwise. + */ + public boolean getLoop() { + return loop; + } + + /** + * Gets the relative volume (subVolume) for the music track. + * + * @return The relative volume for the track, typically a value between 0.0 and 1.0. + */ + public float getSubVolume() { + return subVolume; + } +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/SoundAsset.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/SoundAsset.java new file mode 100644 index 00000000..32749c3c --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/SoundAsset.java @@ -0,0 +1,41 @@ +package pp.mdga.client.Acoustic; + +/** + * Enum representing various sound assets used in the game. + * Each constant corresponds to a specific sound effect used throughout the game. + * These sounds are associated with various events and actions, such as dice rolls, + * turn changes, piece movements, and game outcomes. + */ +enum SoundAsset { + DICE_ROLL(""), + TURN_START(""), + TURN_END(""), + PIECE_END(""), + PIECE_MOVE(""), + PIECE_LOST(""), + SELECT(""), + DESELECT(""), + HURRY(""), + VICTORY("LevelUp2.wav"), + LOST("GameOver.wav"); + + private final String path; + + /** + * Constructs a new SoundAsset object with the specified name. + * + * @param name The name of the sound file. + */ + SoundAsset(String name) { + this.path = "sound/" + name; + } + + /** + * Gets the file path of the sound effect. + * + * @return The path to the sound file (relative to the sound folder). + */ + public String getPath() { + return path; + } +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/SoundAssetDelayVolume.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/SoundAssetDelayVolume.java new file mode 100644 index 00000000..ad7ded23 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Acoustic/SoundAssetDelayVolume.java @@ -0,0 +1,7 @@ +package pp.mdga.client.Acoustic; + +/** + * A record that encapsulates a sound asset along with its playback settings: + * the relative volume (subVolume) and a delay before it starts playing. + */ +record SoundAssetDelayVolume(SoundAsset asset, float subVolume, float delay) { } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/ActionSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/ActionSynchronizer.java deleted file mode 100644 index 977969b2..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/ActionSynchronizer.java +++ /dev/null @@ -1,5 +0,0 @@ -package pp.mdga.client; - -public class ActionSynchronizer { - -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Animation/AnimationHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Animation/AnimationHandler.java index 7047fff5..07307307 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/Animation/AnimationHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Animation/AnimationHandler.java @@ -11,7 +11,7 @@ public AnimationHandler(MdgaApp app) { this.app = app; } - public void playAnimation(AnimationType type) { + public void playAnimation(MdgaAnimation type) { } @@ -23,7 +23,7 @@ public void update() { if(animation.isOver()) { animation = null; - //trigger next state + //trigger next state in model } } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Animation/AnimationType.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Animation/MdgaAnimation.java similarity index 56% rename from Projekte/mdga/client/src/main/java/pp/mdga/client/Animation/AnimationType.java rename to Projekte/mdga/client/src/main/java/pp/mdga/client/Animation/MdgaAnimation.java index 5d2d0233..4d1e0fff 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/Animation/AnimationType.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Animation/MdgaAnimation.java @@ -1,4 +1,4 @@ package pp.mdga.client.Animation; -public enum AnimationType { +public enum MdgaAnimation { } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/AssetOnMap.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/AssetOnMap.java index 3900f56a..09a867c5 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/AssetOnMap.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/AssetOnMap.java @@ -1,3 +1,3 @@ package pp.mdga.client.Board; -public record AssetOnMap(Asset asset, int x, int y, float rot){} +record AssetOnMap(BoardAsset asset, int x, int y, float rot){} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/Asset.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/BoardAsset.java similarity index 91% rename from Projekte/mdga/client/src/main/java/pp/mdga/client/Board/Asset.java rename to Projekte/mdga/client/src/main/java/pp/mdga/client/Board/BoardAsset.java index 7134e595..002fd928 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/Asset.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/BoardAsset.java @@ -1,7 +1,7 @@ package pp.mdga.client.Board; -public enum Asset { - bigTent(0.57f), +enum BoardAsset { + bigTent, cardStack, cir, heer, @@ -17,7 +17,7 @@ public enum Asset { node_bonus("./node_normal/node_normal.j3o", "./node_normal/node_bonus_diff.png"), radar, shieldCard, - ship(0.9f), + ship, smallTent, swapCard, tank, @@ -28,20 +28,20 @@ public enum Asset { private final String diffPath; private final float size; - Asset(){ + BoardAsset(){ String folderFileName = "./" + name() + "/" + name(); this.modelPath = folderFileName + ".j3o"; this.diffPath = folderFileName + "_diff.png"; this.size = 1f; } - Asset(String modelPath, String diffPath){ + BoardAsset(String modelPath, String diffPath){ this.modelPath = modelPath; this.diffPath = diffPath; this.size = 1f; } - Asset(float size){ + BoardAsset(float size){ String folderFileName = "./" + name() + "/" + name(); this.modelPath = folderFileName + ".j3o"; this.diffPath = folderFileName + "_diff.png"; diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/BoardView.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/BoardView.java index b4412c5e..eb0f29c9 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/BoardView.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/BoardView.java @@ -7,37 +7,32 @@ import com.jme3.scene.control.AbstractControl; import pp.mdga.client.MdgaApp; import pp.mdga.game.Color; -import pp.mdga.game.Node; -import java.awt.geom.Point2D; import java.util.*; public class BoardView { private static final float GRID_SIZE = 1.72f; private static final float GRID_ELEVATION = 0.0f; - private static final int GRID_EXTEND = 5; private static final String MAP_NAME = "map.mdga"; - private final MdgaApp mdgaApp; + private final MdgaApp app; - private PileControl drawPile = new PileControl(); - private PileControl discardPile = new PileControl(); + private PileControl drawPile = null; + private PileControl discardPile = null; private ArrayList infield = new ArrayList<>(40); private Map pieces; private Map> playerMap; - public BoardView(int playerCount, MdgaApp mdgaApp) { - assert(2 <= playerCount && playerCount <= 4); - assert(mdgaApp != null); + public BoardView(MdgaApp app) { + assert(app != null) : "app is null"; - this.mdgaApp = mdgaApp; + this.app = app; this.pieces = new HashMap<>(); this.playerMap = new HashMap<>(); - initMap(); } @@ -45,7 +40,7 @@ private void addFigureToPlayerMap(Color col, AssetOnMap assetOnMap){ List inMap = playerMap.getOrDefault(col, new ArrayList<>()); inMap.add(assetOnMap); - if(inMap.size() > 4) throw new RuntimeException("to many assets for one player"); + assert(inMap.size() <= 4) : "to many assets for one player"; playerMap.put(col, inMap); } @@ -55,17 +50,17 @@ private void initMap() { for (AssetOnMap assetOnMap : assetOnMaps){ switch (assetOnMap.asset()){ - case lw -> addFigureToPlayerMap(assetToColor(Asset.lw), assetOnMap); - case heer -> addFigureToPlayerMap(assetToColor(Asset.heer), assetOnMap); - case cir -> addFigureToPlayerMap(assetToColor(Asset.cir), assetOnMap); - case marine -> addFigureToPlayerMap(assetToColor(Asset.marine), assetOnMap); - case node_normal, node_bonus, node_start -> displayAndControl(assetOnMap, new NodeControl()); + case lw -> addFigureToPlayerMap(assetToColor(BoardAsset.lw), assetOnMap); + case heer -> addFigureToPlayerMap(assetToColor(BoardAsset.heer), assetOnMap); + case cir -> addFigureToPlayerMap(assetToColor(BoardAsset.cir), assetOnMap); + case marine -> addFigureToPlayerMap(assetToColor(BoardAsset.marine), assetOnMap); + case node_normal, node_bonus, node_start -> infield.addLast(displayAndControl(assetOnMap, new NodeControl())); default -> displayAsset(assetOnMap); } } } - private Color assetToColor(Asset asset){ + private Color assetToColor(BoardAsset asset){ return switch(asset){ case lw -> Color.AIRFORCE; case heer -> Color.ARMY; @@ -75,31 +70,28 @@ private Color assetToColor(Asset asset){ }; } - private Spatial createModel(Asset asset, Vector3f pos, float rot){ + private Spatial createModel(BoardAsset asset, Vector3f pos, float rot){ String modelName = asset.getModelPath(); String texName = asset.getDiffPath(); - Spatial model = mdgaApp.getAssetManager().loadModel(modelName); + Spatial model = app.getAssetManager().loadModel(modelName); model.scale(asset.getSize()); model.rotate((float) Math.toRadians(0), 0, (float) Math.toRadians(90 + rot)); model.setLocalTranslation(pos); model.setShadowMode(RenderQueue.ShadowMode.CastAndReceive); - Material mat = new Material(mdgaApp.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md"); - mat.setTexture("DiffuseMap", mdgaApp.getAssetManager().loadTexture(texName)); + Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md"); + mat.setTexture("DiffuseMap", app.getAssetManager().loadTexture(texName)); model.setMaterial(mat); - mdgaApp.getRootNode().attachChild(model); + app.getRootNode().attachChild(model); return model; } private static Vector3f gridToWorld(int x, int y) { - assert(-GRID_EXTEND <= x && x <= GRID_EXTEND); - assert(-GRID_EXTEND <= y && y < GRID_EXTEND); - return new Vector3f(GRID_SIZE * x, GRID_SIZE * y, GRID_ELEVATION); } public void addPlayer(Color color, UUID uuid){ List playerAssets = playerMap.get(color); - if (playerAssets == null) throw new RuntimeException("Assets for Player color are not defined"); + assert(playerAssets != null) : "Assets for Player color are not defined"; for (AssetOnMap assetOnMap : playerAssets){ pieces.put(uuid, displayAndControl(assetOnMap, new PieceControl())); diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/MapLoader.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/MapLoader.java index 2e813acf..4d2e2f63 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/MapLoader.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/MapLoader.java @@ -27,19 +27,22 @@ public static List loadMap(String mapName) { if(entry.charAt(0) == '#') continue; String[] parts = entry.trim().split(" "); - assert(parts.length == 3); + if(parts.length != 3){ + parts = parts; + } + assert(parts.length == 3) : "MapLoader: line has not 3 parts"; String assetName = parts[0]; String[] coordinates = parts[1].split(","); - assert(coordinates.length == 2); + assert(coordinates.length == 2) : "MapLoade: coordinates are wrong"; int x = Integer.parseInt(coordinates[0]); int y = Integer.parseInt(coordinates[1]); float rot = Float.parseFloat(parts[2]); - Asset asset = getLoadedAsset(assetName); + BoardAsset asset = getLoadedAsset(assetName); assetsOnMap.add(new AssetOnMap(asset, x, y, rot)); } } catch (IOException e) { @@ -51,26 +54,26 @@ public static List loadMap(String mapName) { return assetsOnMap; } - private static Asset getLoadedAsset(String assetName) { + private static BoardAsset getLoadedAsset(String assetName) { return switch(assetName){ - case "lw" -> Asset.lw; - case "cir" -> Asset.cir; - case "marine" -> Asset.marine; - case "heer" -> Asset.heer; - case "node" -> Asset.node_normal; - case "node_start" -> Asset.node_start; - case "node_bonus" -> Asset.node_bonus; - case "node_home_blue" -> Asset.node_home_blue; - case "node_home_yellow" -> Asset.node_home_yellow; - case "node_home_black" -> Asset.node_home_black; - case "node_home_green" -> Asset.node_home_green; - case "world" -> Asset.world; - case "jet" -> Asset.jet; - case "big_tent" -> Asset.bigTent; - case "small_tent" -> Asset.smallTent; - case "radar" -> Asset.radar; - case "ship" -> Asset.ship; - case "tank" -> Asset.tank; + case "lw" -> BoardAsset.lw; + case "cir" -> BoardAsset.cir; + case "marine" -> BoardAsset.marine; + case "heer" -> BoardAsset.heer; + case "node" -> BoardAsset.node_normal; + case "node_start" -> BoardAsset.node_start; + case "node_bonus" -> BoardAsset.node_bonus; + case "node_home_blue" -> BoardAsset.node_home_blue; + case "node_home_yellow" -> BoardAsset.node_home_yellow; + case "node_home_black" -> BoardAsset.node_home_black; + case "node_home_green" -> BoardAsset.node_home_green; + case "world" -> BoardAsset.world; + case "jet" -> BoardAsset.jet; + case "big_tent" -> BoardAsset.bigTent; + case "small_tent" -> BoardAsset.smallTent; + case "radar" -> BoardAsset.radar; + case "ship" -> BoardAsset.ship; + case "tank" -> BoardAsset.tank; default -> throw new IllegalStateException("Unexpected value: " + assetName); }; } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/PileControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/PileControl.java index 4cdc7db1..67a4d994 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/PileControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Board/PileControl.java @@ -1,5 +1,5 @@ package pp.mdga.client.Board; -public class PileControl { +class PileControl { } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/DialogView.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/DialogView.java index 462da741..f7c578e5 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/DialogView.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/DialogView.java @@ -1,5 +1,26 @@ package pp.mdga.client.Dialog; -public class DialogView { +import pp.dialog.DialogManager; +import pp.mdga.client.MdgaApp; +public class DialogView { + private MdgaApp app; + + private DialogManager dialogManager = new DialogManager(app); + + private StartDialog dialog; + + public DialogView(MdgaApp app) { + this.app = app; + } + + DialogManager getDialogManager() { + return dialogManager; + } + + public void mainMenu() { + //dialogManager = new DialogManager(app); + //di + //MainMenuDialog mainMenuDialog = new MainMenuDialog(app); + } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/InterruptDialog.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/InterruptDialog.java new file mode 100644 index 00000000..917a9401 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/InterruptDialog.java @@ -0,0 +1,4 @@ +package pp.mdga.client.Dialog; + +public class InterruptDialog { +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/StartDialog.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/StartDialog.java index 76a8c0fc..19b0a6cb 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/StartDialog.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Dialog/StartDialog.java @@ -1,5 +1,35 @@ package pp.mdga.client.Dialog; -public class StartDialog { +import com.simsilica.lemur.Checkbox; +import com.simsilica.lemur.Container; +import com.simsilica.lemur.Label; +import com.simsilica.lemur.component.SpringGridLayout; +import pp.dialog.DialogBuilder; +import pp.dialog.SimpleDialog; +import pp.mdga.client.MdgaApp; +public class StartDialog extends SimpleDialog { + StartDialog(MdgaApp app) { + super(app.getDialogView().getDialogManager()); + + Checkbox serverHost = new Checkbox("sdgfsdg"); + serverHost.setChecked(false); + //serverHost.addClickCommands(s -> toggleServerHost()); + + final Container input = new Container(new SpringGridLayout()); + input.addChild(new Label("sdgsgsdg")); + //input.addChild(host, 1); + input.addChild(new Label("sdfdsgsdgsdg")); + //input.addChild(port, 1); + input.addChild(serverHost); + + DialogBuilder.simple(app.getDialogView().getDialogManager()) + .setTitle("server.dialog") + .setOkButton("button.connect") + .setNoButton("button.cancel") + .setOkClose(false) + .setNoClose(false) + .build(this); + + } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java index 699d6152..b4b9e2bf 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java @@ -1,36 +1,31 @@ package pp.mdga.client; import com.jme3.app.SimpleApplication; +import com.jme3.system.NanoTimer; +import pp.mdga.client.Acoustic.AcousticHandler; +import pp.mdga.client.Acoustic.MdgaSound; import pp.mdga.client.Animation.AnimationHandler; -import com.jme3.light.AmbientLight; -import com.jme3.light.DirectionalLight; -import com.jme3.material.Material; -import com.jme3.math.ColorRGBA; -import com.jme3.math.Vector3f; -import com.jme3.renderer.queue.RenderQueue; -import com.jme3.scene.Spatial; -import com.jme3.shadow.DirectionalLightShadowRenderer; import com.jme3.system.AppSettings; -import pp.mdga.client.Board.Asset; -import pp.mdga.client.Board.AssetOnMap; import pp.mdga.client.Board.BoardView; -import pp.mdga.client.Board.MapLoader; -import pp.mdga.game.Color; - -import java.util.List; -import java.util.UUID; +import pp.mdga.client.Dialog.DialogView; public class MdgaApp extends SimpleApplication { private AnimationHandler animationHandler; + private AcousticHandler acousticHandler; private BoardView boardView; + private DialogView dialogView; + + NanoTimer test = new NanoTimer(); + private MdgaState testState = MdgaState.MAIN; public static void main(String[] args) { - MdgaApp app = new MdgaApp(); AppSettings settings = new AppSettings(true); settings.setSamples(128); settings.setCenterWindow(true); - settings.setWidth(1300); - settings.setHeight(1000); + settings.setWidth(1280); + settings.setHeight(720); + + MdgaApp app = new MdgaApp(); app.setSettings(settings); app.setShowSettings(false); app.start(); @@ -39,38 +34,52 @@ public static void main(String[] args) { @Override public void simpleInitApp() { animationHandler = new AnimationHandler(this); - boardView = new BoardView(4,this); - - //display all pieces - boardView.addPlayer(Color.NAVY, UUID.randomUUID()); - boardView.addPlayer(Color.AIRFORCE, UUID.randomUUID()); - boardView.addPlayer(Color.ARMY, UUID.randomUUID()); - boardView.addPlayer(Color.CYBER, UUID.randomUUID()); - - - flyCam.setEnabled(true); - int zoom = 40; - cam.setLocation(new Vector3f(-zoom,0,zoom)); - cam.lookAt(new Vector3f(0,0,0), new Vector3f(0,0,1)); - - DirectionalLight sun = new DirectionalLight(); - sun.setColor(ColorRGBA.White); - sun.setDirection(new Vector3f(-0.3f,0,-1)); - rootNode.addLight(sun); - AmbientLight ambient = new AmbientLight(); - ambient.setColor(new ColorRGBA(0.3f,0.3f,0.3f,1)); - rootNode.addLight(ambient); - - final int SHADOWMAP_SIZE=1024*8; - DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(assetManager, SHADOWMAP_SIZE, 4); - dlsr.setLight(sun); - viewPort.addProcessor(dlsr); + acousticHandler = new AcousticHandler(this); + boardView = new BoardView(this); + dialogView = new DialogView(this); + //dialogView.mainMenu(); + //acousticHandler.playState(MdgaState.GAME); + acousticHandler.playSound(MdgaSound.LOST); + acousticHandler.playSound(MdgaSound.VICTORY); } @Override 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; + } + + public DialogView getDialogView() { + return dialogView; } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaState.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaState.java new file mode 100644 index 00000000..be3d32de --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaState.java @@ -0,0 +1,48 @@ +package pp.mdga.client; + +import pp.mdga.notification.Notification; +import pp.mdga.notification.PieceInGameNotification; +import pp.mdga.notification.PlayerInGameNotification; + +public enum MdgaState { + NONE { + @Override + void handleNotification(MdgaApp app, Notification notification) { + throw new RuntimeException("unexpected notification"); + } + }, + MAIN { + @Override + void handleNotification(MdgaApp app, Notification notification) { + throw new RuntimeException("unexpected notification"); + } + }, + LOBBY { + @Override + void handleNotification(MdgaApp app, Notification notification) { + throw new RuntimeException("unexpected notification"); + } + }, + GAME { + @Override + void handleNotification(MdgaApp app, Notification notification) { + if(notification instanceof PlayerInGameNotification) { + //TODO + } + else if(notification instanceof PieceInGameNotification){ + //TODO + } + else { + throw new RuntimeException("unexpected notification"); + } + } + }, + CEREMONY { + @Override + void handleNotification(MdgaApp app, Notification notification) { + throw new RuntimeException("unexpected notification"); + } + }; + + abstract void handleNotification(MdgaApp app, Notification notification); +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java new file mode 100644 index 00000000..2a95a2a7 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java @@ -0,0 +1,23 @@ +package pp.mdga.client; + +import pp.mdga.notification.Notification; + +import java.util.ArrayList; + +public class NotificationSynchronizer { + private final MdgaApp app; + private MdgaState state = MdgaState.MAIN; + + NotificationSynchronizer(MdgaApp app) { + this.app = app; + } + + void update() { + ArrayList notifications = new ArrayList<>(); + //TODO fetch model notifications + + for (Notification n : notifications) { + state.handleNotification(app, n); + } + } +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/CeremonyState.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/State/CeremonyState.java deleted file mode 100644 index 47b40346..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/CeremonyState.java +++ /dev/null @@ -1,5 +0,0 @@ -package pp.mdga.client.State; - -public class CeremonyState { - -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/GameState.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/State/GameState.java deleted file mode 100644 index deddeb1d..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/GameState.java +++ /dev/null @@ -1,5 +0,0 @@ -package pp.mdga.client.State; - -public class GameState { - -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/LobbyState.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/State/LobbyState.java deleted file mode 100644 index 58777b55..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/LobbyState.java +++ /dev/null @@ -1,5 +0,0 @@ -package pp.mdga.client.State; - -public class LobbyState { - -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/MdgaState.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/State/MdgaState.java deleted file mode 100644 index 8476a7af..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/MdgaState.java +++ /dev/null @@ -1,5 +0,0 @@ -package pp.mdga.client.State; - -public class MdgaState { - -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/MusicState.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/State/MusicState.java deleted file mode 100644 index b1e5484d..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/MusicState.java +++ /dev/null @@ -1,5 +0,0 @@ -package pp.mdga.client.State; - -public class MusicState { - -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/SoundState.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/State/SoundState.java deleted file mode 100644 index f3184745..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/State/SoundState.java +++ /dev/null @@ -1,5 +0,0 @@ -package pp.mdga.client.State; - -public class SoundState { - -} diff --git a/Projekte/mdga/client/src/main/resources/circle_map.mdga b/Projekte/mdga/client/src/main/resources/circle_map.mdga new file mode 100644 index 00000000..71c74643 --- /dev/null +++ b/Projekte/mdga/client/src/main/resources/circle_map.mdga @@ -0,0 +1,66 @@ +world 0,0 + +# jet 0,0 + +#Nodes für Map +node_start 8,0 +node 8,1 +node 8,2 +node 7,3 +node_bonus 6,4 +node 5,5 +node 4,6 +node 3,7 +node 2,8 +node 1,8 +node_start 0,8 +node -1,8 +node -2,8 +node -3,7 +node_bonus -4,6 +node -5,5 +node -6,4 +node -7,3 +node -8,2 +node -8,1 +node_start -8,0 +node -8,-1 +node -8,-2 +node -7,-3 +node_bonus -6,-4 +node -5,-5 +node -4,-6 +node -3,-7 +node -2,-8 +node -1,-8 +node_start 0,-8 +node 1,-8 +node 2,-8 +node 3,-7 +node_bonus 4,-6 +node 5,-5 +node 6,-4 +node 7,-3 +node 8,-2 +node 8,-1 + +#Node Home +node_home_blue 7,0 +node_home_blue 6,0 +node_home_blue 5,0 +node_home_blue 4,0 + +node_home_black 0,4 +node_home_black 0,5 +node_home_black 0,6 +node_home_black 0,7 + +node_home_yellow 0,-4 +node_home_yellow 0,-5 +node_home_yellow 0,-6 +node_home_yellow 0,-7 + +node_home_green -4,0 +node_home_green -5,0 +node_home_green -6,0 +node_home_green -7,0 diff --git a/Projekte/mdga/client/src/main/resources/map.mdga b/Projekte/mdga/client/src/main/resources/map.mdga index 53b8a746..cf955999 100644 --- a/Projekte/mdga/client/src/main/resources/map.mdga +++ b/Projekte/mdga/client/src/main/resources/map.mdga @@ -93,9 +93,9 @@ node 1,-4 0 node 1,-5 0 node 0,-5 0 node_start -1,-5 0 -node -1,-4 0 0 -node -1,-3 0 0 -node -1,-2 0 0 +node -1,-4 0 +node -1,-3 0 +node -1,-2 0 node_bonus -1,-1 0 node -2,-1 0 node -3,-1 0 diff --git a/Projekte/mdga/client/src/main/resources/music/80s,Disco,Life.wav b/Projekte/mdga/client/src/main/resources/music/80s,Disco,Life.wav new file mode 100644 index 00000000..9f394d8b Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/80s,Disco,Life.wav differ diff --git a/Projekte/mdga/client/src/main/resources/music/CREDIT.txt b/Projekte/mdga/client/src/main/resources/music/CREDIT.txt new file mode 100644 index 00000000..487d2c13 --- /dev/null +++ b/Projekte/mdga/client/src/main/resources/music/CREDIT.txt @@ -0,0 +1,22 @@ +# Credit + +## Free SynthWave Music Pack + +See "Free SynthWave Music Pack License.pdf" for LICENCE information. + + - 80s,Dico,Live.wav + - LaserParty.wav + - NeonRoadTrip.wav + - NoPressureTrance.wav + - RetroNoir.wav + - SpaceInvaders.wav + - TheSynthRave.SynthWave + +## Short Loopable Background Music + + https://joshuuu.itch.io/short-loopable-background-music + + Free for personal or commercial use as long as you don't redistribute as your own. Donations also welcome! Please add jhaeka to your credits. :) + + - DeadPlanet.wav + - Spaceship.wav diff --git a/Projekte/mdga/client/src/main/resources/music/DeadPlanet.wav b/Projekte/mdga/client/src/main/resources/music/DeadPlanet.wav new file mode 100644 index 00000000..98d78964 Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/DeadPlanet.wav differ diff --git a/Projekte/mdga/client/src/main/resources/music/Free SynthWave Music Pack License.pdf b/Projekte/mdga/client/src/main/resources/music/Free SynthWave Music Pack License.pdf new file mode 100644 index 00000000..de1833e4 Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/Free SynthWave Music Pack License.pdf differ diff --git a/Projekte/mdga/client/src/main/resources/music/LaserParty.wav b/Projekte/mdga/client/src/main/resources/music/LaserParty.wav new file mode 100644 index 00000000..7b1545f4 Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/LaserParty.wav differ diff --git a/Projekte/mdga/client/src/main/resources/music/NeonRoadTrip.wav b/Projekte/mdga/client/src/main/resources/music/NeonRoadTrip.wav new file mode 100644 index 00000000..6f686d35 Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/NeonRoadTrip.wav differ diff --git a/Projekte/mdga/client/src/main/resources/music/NoPressureTrance.wav b/Projekte/mdga/client/src/main/resources/music/NoPressureTrance.wav new file mode 100644 index 00000000..9a67bc39 Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/NoPressureTrance.wav differ diff --git a/Projekte/mdga/client/src/main/resources/music/RetroNoir.wav b/Projekte/mdga/client/src/main/resources/music/RetroNoir.wav new file mode 100644 index 00000000..c7415be5 Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/RetroNoir.wav differ diff --git a/Projekte/mdga/client/src/main/resources/music/SpaceInvaders.wav b/Projekte/mdga/client/src/main/resources/music/SpaceInvaders.wav new file mode 100644 index 00000000..ee24985c Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/SpaceInvaders.wav differ diff --git a/Projekte/mdga/client/src/main/resources/music/Spaceship.wav b/Projekte/mdga/client/src/main/resources/music/Spaceship.wav new file mode 100644 index 00000000..d9be3316 Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/Spaceship.wav differ diff --git a/Projekte/mdga/client/src/main/resources/music/SynthWave Music Pack Square.png b/Projekte/mdga/client/src/main/resources/music/SynthWave Music Pack Square.png new file mode 100644 index 00000000..e6e07e8a Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/SynthWave Music Pack Square.png differ diff --git a/Projekte/mdga/client/src/main/resources/music/TheSynthRave.wav b/Projekte/mdga/client/src/main/resources/music/TheSynthRave.wav new file mode 100644 index 00000000..512c6160 Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/music/TheSynthRave.wav differ diff --git a/Projekte/mdga/client/src/main/resources/sound/GameOver.wav b/Projekte/mdga/client/src/main/resources/sound/GameOver.wav new file mode 100644 index 00000000..08b99121 Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/sound/GameOver.wav differ diff --git a/Projekte/mdga/client/src/main/resources/sound/LevelUp2.wav b/Projekte/mdga/client/src/main/resources/sound/LevelUp2.wav new file mode 100644 index 00000000..53483a34 Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/sound/LevelUp2.wav differ diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/effect/Effect.java b/Projekte/mdga/model/src/main/java/pp.mdga/effect/Effect.java deleted file mode 100644 index 7a4168b1..00000000 --- a/Projekte/mdga/model/src/main/java/pp.mdga/effect/Effect.java +++ /dev/null @@ -1,4 +0,0 @@ -package pp.mdga.effect; - -public interface Effect { -} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/game/Board.java b/Projekte/mdga/model/src/main/java/pp.mdga/game/Board.java index dfd95a77..8b48d6e4 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/game/Board.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/game/Board.java @@ -6,7 +6,7 @@ * This class will be used to hold all Board relevant data. */ public class Board { - private Map playerData; + private Map playerData; private Node[] infield; /** @@ -16,7 +16,12 @@ public Board() { infield = new Node[40]; for (int i = 0; i < 40; i++) { if (i % 10 == 0) { - infield[i] = new StartNode(); + infield[i] = new StartNode( + i == 0 ? Color.ARMY : + i == 10 ? Color.AIRFORCE : + i == 20 ? Color.CYBER : + Color.NAVY + ); } else if (i == 4 || i == 14 || i == 24 || i == 34) { infield[i] = new BonusNode(); } else { @@ -30,7 +35,7 @@ public Board() { * * @return the playerData */ - public Map getPlayerData() { + public Map getPlayerData() { return playerData; } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/game/Card.java b/Projekte/mdga/model/src/main/java/pp.mdga/game/Card.java deleted file mode 100644 index a3296a3a..00000000 --- a/Projekte/mdga/model/src/main/java/pp.mdga/game/Card.java +++ /dev/null @@ -1,34 +0,0 @@ -package pp.mdga.game; -/** - * This class is used to create a card - */ -public class Card { - private BonusCard type; - - /** - * This constructor is used to create a new card - * - * @param type the type of the card - */ - public Card(BonusCard type) { - this.type = type; - } - - /** - * This method is used to get the type of the card - * - * @return the type of the card - */ - public BonusCard getType() { - return type; - } - - /** - * This method is used to set the type of the card - * - * @param type the new type of the card - */ - public void setType(BonusCard type) { - this.type = type; - } -} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/game/Game.java b/Projekte/mdga/model/src/main/java/pp.mdga/game/Game.java index 2cc4661e..92a5dd30 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/game/Game.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/game/Game.java @@ -5,15 +5,17 @@ import java.util.Map; /** - * This class will be used to handle the data stored in the model + * The Game class represents the game state of the Ludo game. + * It contains all the information needed to play the game. + * The game state is updated by the game logic. */ public class Game { private int diceModifier = 1; private int diceEyes; private Map players; private Statistic gameStatistics; - private ArrayList drawPile; - private ArrayList discardPile = new ArrayList<>(); + private ArrayList drawPile; + private ArrayList discardPile = new ArrayList<>(); private Board board; private Color activeColor; private LinkedList order; @@ -22,16 +24,238 @@ public class Game { private static final int AMOUNT_OF_TURBO_CARDS = 16; private static final int AMOUNT_OF_SHIELD_AND_SWAP_CARDS = 12; + /** + * This constructor creates a new Game object. + */ public Game(){ gameStatistics = new Statistic(); drawPile = new ArrayList<>(); for (int i = 0; i < AMOUNT_OF_TURBO_CARDS; i++) { - drawPile.add(new Card(BonusCard.TURBO)); + drawPile.add(BonusCard.TURBO); } for (int i = 0; i < AMOUNT_OF_SHIELD_AND_SWAP_CARDS; i++) { - drawPile.add(new Card(BonusCard.SHIELD)); - drawPile.add(new Card(BonusCard.SWAP)); + drawPile.add(BonusCard.SWAP); + drawPile.add(BonusCard.SHIELD); } board = new Board(); } + + /** + * This method returns the dice modifier. + * + * @return the dice modifier + */ + public int getDiceModifier() { + return diceModifier; + } + + /** + * This method sets the dice modifier. + * + * @param diceModifier the new dice modifier + */ + public void setDiceModifier(int diceModifier) { + this.diceModifier = diceModifier; + } + + /** + * This method returns the dice eyes. + * + * @return the dice eyes + */ + public int getDiceEyes() { + return diceEyes; + } + + /** + * This method sets the dice eyes. + * + * @param diceEyes the new dice eyes + */ + public void setDiceEyes(int diceEyes) { + this.diceEyes = diceEyes; + } + + /** + * This method returns the players. + * + * @return the players + */ + public Map getPlayers() { + return players; + } + + /** + * This method sets the players. + * + * @param players the new players + */ + public void setPlayers(Map players) { + this.players = players; + } + + /** + * This method returns the game statistics. + * + * @return the game statistics + */ + public Statistic getGameStatistics() { + return gameStatistics; + } + + /** + * This method sets the game statistics. + * + * @param gameStatistics the new game statistics + */ + public void setGameStatistics(Statistic gameStatistics) { + this.gameStatistics = gameStatistics; + } + + /** + * This method returns the draw pile. + * + * @return the draw pile + */ + public ArrayList getDrawPile() { + return drawPile; + } + + /** + * This method sets the draw pile. + * + * @param drawPile the new draw pile + */ + public void setDrawPile(ArrayList drawPile) { + this.drawPile = drawPile; + } + + /** + * This method returns the discard pile. + * + * @return the discard pile + */ + public ArrayList getDiscardPile() { + return discardPile; + } + + /** + * This method sets the discard pile. + * + * @param discardPile the new discard pile + */ + public void setDiscardPile(ArrayList discardPile) { + this.discardPile = discardPile; + } + + /** + * This method returns the board. + * + * @return the board + */ + public Board getBoard() { + return board; + } + + /** + * This method sets the board. + * + * @param board the new board + */ + public void setBoard(Board board) { + this.board = board; + } + + /** + * This method returns the active color. + * + * @return the active color + */ + public Color getActiveColor() { + return activeColor; + } + + /** + * This method sets the active color. + * + * @param activeColor the new active color + */ + public void setActiveColor(Color activeColor) { + this.activeColor = activeColor; + } + + /** + * This method returns the order of the players. + * + * @return the order of the players + */ + public LinkedList getOrder() { + return order; + } + + /** + * This method sets the order of the players. + * + * @param order the new order of the players + */ + public void setOrder(LinkedList order) { + this.order = order; + } + + /** + * This method returns the player connection ID. + * + * @return the player connection ID + */ + public Map getPlayerConnectionID() { + return playerConnectionID; + } + + /** + * This method sets the player connection ID. + * + * @param playerConnectionID the new player connection ID + */ + public void setPlayerConnectionID(Map playerConnectionID) { + this.playerConnectionID = playerConnectionID; + } + + /** + * This method sets the player connection ID. + * + * @param color the color of the player + * @param connectionID the new connection ID + */ + public void setPlayerConnectionID(Color color, int connectionID) { + playerConnectionID.put(color, connectionID); + } + + /** + * This method returns the player connection ID. + * + * @param color the color of the player + * @return the player connection ID + */ + public int getPlayerConnectionID(Color color) { + return playerConnectionID.get(color); + } + + /** + * This method adds a player to the game. + * + * @param color the color of the player + * @param player the player to be added + */ + public void addPlayer(Color color, Player player) { + players.put(color, player); + } + + /** + * This method removes a player from the game. + * + * @param color the color of the player + */ + public void removePlayer(Color color) { + players.remove(color); + } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/game/Piece.java b/Projekte/mdga/model/src/main/java/pp.mdga/game/Piece.java index 47d3041c..e68f3d26 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/game/Piece.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/game/Piece.java @@ -1,36 +1,75 @@ package pp.mdga.game; +/** + * This class will be used to hold all Piece relevant data. + */ public class Piece { private ShieldState shield; private PieceState state; private Color color; + /** + * This constructor is used to create a new Piece + * + * @param color the color of the piece + * @param state the state of the piece + */ public Piece(Color color, PieceState state) { this.color = color; this.state = state; shield = ShieldState.NONE; } + /** + * This method is used to get the color of the piece + * + * @return the color of the piece + */ public void setShield(ShieldState shield) { this.shield = shield; } + /** + * This method is used to get the color of the piece + * + * @return the color of the piece + */ public ShieldState getShield() { return shield; } + /** + * This method is used to get the color of the piece + * + * @param state the state of the piece + */ public void setState(PieceState state) { this.state = state; } + /** + * This method is used to get the color of the piece + * + * @return the color of the piece + */ public PieceState getState() { return state; } + /** + * This method is used to get the color of the piece + * + * @return the color of the piece + */ public boolean isShielded() { return shield == ShieldState.ACTIVE; } + /** + * This method is used to get the color of the piece + * + * @return the color of the piece + */ public boolean isSuppressed() { return shield == ShieldState.SUPPRESSED; } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/game/Player.java b/Projekte/mdga/model/src/main/java/pp.mdga/game/Player.java index cc7d4b05..2a97d27c 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/game/Player.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/game/Player.java @@ -9,7 +9,7 @@ public class Player { private String name; private Statistic playerStatistic; - private ArrayList handCards; + private ArrayList handCards; private final int id; /** @@ -53,17 +53,17 @@ public Statistic getPlayerStatistic() { * * @return the handCards of the player */ - public ArrayList getHandCards() { + public ArrayList getHandCards() { return handCards; } /** * This method adds a new handCard to the player * - * @param cards the card to be added to the players hand + * @param card the card to be added to the players hand */ - public void addHandCards(Card cards){ - handCards.add(cards); + public void addHandCards(BonusCard card){ + handCards.add(card); } /** @@ -72,8 +72,8 @@ public void addHandCards(Card cards){ * @param card the cards type to be removed * @return the removed card or null if there is none of that card type */ - public Card removeHandCard(Card card) { - Card cardToRemove = handCards.stream().filter(card1 -> card1.getType().equals(card.getType())).findFirst().orElse(null); + public BonusCard removeHandCard(BonusCard card) { + BonusCard cardToRemove = handCards.stream().filter(c -> c.equals(card)).findFirst().orElse(null); if (cardToRemove != null) { handCards.remove(cardToRemove); } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/game/StartNode.java b/Projekte/mdga/model/src/main/java/pp.mdga/game/StartNode.java index 35130151..85e70cb3 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/game/StartNode.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/game/StartNode.java @@ -2,7 +2,11 @@ public class StartNode extends Node { - public StartNode() {} + public StartNode(Color color) { + this.color = color; + } + + private Color color; /** * This method is used to set a new Occupant @@ -16,4 +20,22 @@ public void setOccupant(Piece occupant) { } this.occupant = occupant; } + + /** + * This method is used to get the color of the node + * + * @return the color of the node + */ + public Color getColor() { + return color; + } + + /** + * This method is used to set the color of the node + * + * @param color the new color of the node + */ + public void setColor(Color color) { + this.color = color; + } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/message/client/ClientMessage.java b/Projekte/mdga/model/src/main/java/pp.mdga/message/client/ClientMessage.java index 2b9f4111..11dae3e0 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/message/client/ClientMessage.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/message/client/ClientMessage.java @@ -3,8 +3,10 @@ import com.jme3.network.AbstractMessage; public abstract class ClientMessage extends AbstractMessage { + protected ClientMessage() { super(true); } + public abstract void accept(ClientInterpreter interpreter, int from); } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/ActivePlayerNotification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/ActivePlayerNotification.java new file mode 100644 index 00000000..8a2e0339 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/ActivePlayerNotification.java @@ -0,0 +1,9 @@ +package pp.mdga.notification; + +import pp.mdga.game.Color; + +public class ActivePlayerNotification extends Notification { + ActivePlayerNotification(Color color) { + + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/DrawCardNotification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/DrawCardNotification.java new file mode 100644 index 00000000..a8c73551 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/DrawCardNotification.java @@ -0,0 +1,10 @@ +package pp.mdga.notification; + +import pp.mdga.game.BonusCard; +import pp.mdga.game.Color; + +public class DrawCardNotification extends Notification { + DrawCardNotification(Color color, BonusCard card) { + + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/InterruptNotification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/InterruptNotification.java new file mode 100644 index 00000000..f9459c55 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/InterruptNotification.java @@ -0,0 +1,9 @@ +package pp.mdga.notification; + +import pp.mdga.game.Color; + +public class InterruptNotification extends Notification { + InterruptNotification(Color color) { + + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/MovePieceNotification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/MovePieceNotification.java new file mode 100644 index 00000000..b35918cc --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/MovePieceNotification.java @@ -0,0 +1,9 @@ +package pp.mdga.notification; + +import pp.mdga.game.Color; + +public class MovePieceNotification extends Notification { + MovePieceNotification(Color color, int nodeIndex) { + + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/Notification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/Notification.java new file mode 100644 index 00000000..3f8be5da --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/Notification.java @@ -0,0 +1,4 @@ +package pp.mdga.notification; + +public abstract class Notification { +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/PieceInGameNotification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/PieceInGameNotification.java new file mode 100644 index 00000000..5e0585fd --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/PieceInGameNotification.java @@ -0,0 +1,11 @@ +package pp.mdga.notification; + +import pp.mdga.game.Color; + +import java.util.UUID; + +public class PieceInGameNotification extends Notification{ + PieceInGameNotification(Color color, UUID id) { + + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/PlayCardNotification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/PlayCardNotification.java new file mode 100644 index 00000000..f2e73063 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/PlayCardNotification.java @@ -0,0 +1,10 @@ +package pp.mdga.notification; + +import pp.mdga.game.BonusCard; +import pp.mdga.game.Color; + +public class PlayCardNotification extends Notification { + PlayCardNotification(Color color, BonusCard card) { + + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/PlayerInGameNotification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/PlayerInGameNotification.java new file mode 100644 index 00000000..c1c77cc9 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/PlayerInGameNotification.java @@ -0,0 +1,9 @@ +package pp.mdga.notification; + +import pp.mdga.game.Color; + +public class PlayerInGameNotification extends Notification { + PlayerInGameNotification(Color color, String name) { + + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/ResumeNotification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/ResumeNotification.java new file mode 100644 index 00000000..6a28137d --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/ResumeNotification.java @@ -0,0 +1,9 @@ +package pp.mdga.notification; + +import pp.mdga.game.Color; + +public class ResumeNotification extends Notification { + ResumeNotification(Color color) { + + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/RollDiceNotification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/RollDiceNotification.java new file mode 100644 index 00000000..48ca8192 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/RollDiceNotification.java @@ -0,0 +1,9 @@ +package pp.mdga.notification; + +import pp.mdga.game.Color; + +public class RollDiceNotification extends Notification{ + RollDiceNotification(Color color, int eyes, int moveNumber) { + + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/notification/SwapPieceNotification.java b/Projekte/mdga/model/src/main/java/pp.mdga/notification/SwapPieceNotification.java new file mode 100644 index 00000000..b287e403 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/notification/SwapPieceNotification.java @@ -0,0 +1,9 @@ +package pp.mdga.notification; + +import java.util.UUID; + +public class SwapPieceNotification extends Notification { + SwapPieceNotification(UUID a, UUID b) { + assert(!a.equals(b)); + } +} diff --git a/Projekte/settings.gradle b/Projekte/settings.gradle index 532a4d06..225769d5 100644 --- a/Projekte/settings.gradle +++ b/Projekte/settings.gradle @@ -32,8 +32,8 @@ } } } -include 'mdga:client' -findProject(':mdga:client')?.name = 'client' -include 'mdga:client' -findProject(':mdga:client')?.name = 'client' + +include 'mdga:client' +include 'mdga:model' +findProject(':mdga:client')?.name = 'client'