Merge branch 'dev/client_koppe' into 'dev_client'

Add acoustics

See merge request progproj/gruppen-ht24/Gruppe-01!2
This commit is contained in:
Felix Koppe
2024-11-16 17:21:21 +00:00
69 changed files with 1572 additions and 200 deletions

View File

@@ -1,18 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="MdgaApp" type="Application" factoryName="Application" singleton="false"
nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="pp.mdga.client.MdgaApp"/>
<module name="Projekte.mdga.client.main"/>
<option name="VM_PARAMETERS" value="-Djava.util.logging.config.file=logging.properties"/>
<option name="WORKING_DIRECTORY" value="$MODULE_WORKING_DIR$"/>
<configuration default="false" name="MdgaApp" type="Application" factoryName="Application" singleton="false" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="pp.mdga.client.MdgaApp" />
<module name="Projekte.mdga.client.main" />
<option name="VM_PARAMETERS" value="-Djava.util.logging.config.file=logging.properties -ea" />
<option name="WORKING_DIRECTORY" value="$MODULE_WORKING_DIR$" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="pp.mdga.client.*"/>
<option name="ENABLED" value="true"/>
<option name="PATTERN" value="pp.mdga.client.Board.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true"/>
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -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<MusicAsset> 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<GameSound> 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<GameSound> 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<SoundAssetDelayVolume> assets = new ArrayList<SoundAssetDelayVolume>();
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();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +0,0 @@
package pp.mdga.client;
public class ActionSynchronizer {
}

View File

@@ -1,7 +1,7 @@
package pp.mdga.client.Animation;
public interface Animation {
void play();
void stop();
boolean isOver();
abstract class Animation {
abstract void play();
abstract void stop();
abstract boolean isOver();
}

View File

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

View File

@@ -1,6 +1,6 @@
package pp.mdga.client.Animation;
public class EmptyAnimation implements Animation {
class EmptyAnimation extends Animation {
@Override
void play() {
//nothing

View File

@@ -1,4 +1,4 @@
package pp.mdga.client.Animation;
public enum AnimationType {
public enum MdgaAnimation {
}

View File

@@ -0,0 +1,3 @@
package pp.mdga.client.Board;
record AssetOnMap(BoardAsset boardAsset, int x, int y){}

View File

@@ -1,6 +1,6 @@
package pp.mdga.client;
package pp.mdga.client.Board;
public enum Asset {
enum BoardAsset {
bigTent,
cardStack,
cir,
@@ -8,13 +8,13 @@ public enum Asset {
jet,
lw,
marine,
node_home_blue("./node_home/node_home.j3o", "./node_home/node_home_blue.png"),
node_home_black("./node_home/node_home.j3o", "./node_home/node_home_black.png"),
node_home_green("./node_home/node_home.j3o", "./node_home/node_home_green.png"),
node_home_yellow("./node_home/node_home.j3o", "./node_home/node_home_yellow.png"),
node_home_blue("./node_home/node_home.j3o", "./node_home/node_home_blue_diff.png"),
node_home_black("./node_home/node_home.j3o", "./node_home/node_home_black_diff.png"),
node_home_green("./node_home/node_home.j3o", "./node_home/node_home_green_diff.png"),
node_home_yellow("./node_home/node_home.j3o", "./node_home/node_home_yellow_diff.png"),
node_normal,
node_start("./node_normal/node_normal.j3o", "./node_normal/node_normal_start.png"),
node_bonus("./node_normal/node_normal.j3o", "./node_normal/node_normal_bonus.png"),
node_start("./node_normal/node_normal.j3o", "./node_normal/node_start_diff.png"),
node_bonus("./node_normal/node_normal.j3o", "./node_normal/node_bonus_diff.png"),
radar,
shieldCard,
ship,
@@ -22,26 +22,26 @@ public enum Asset {
swapCard,
tank,
turboCard,
world(1.1f);
world(1.2f);
private final String modelPath;
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";

View File

@@ -1,30 +1,95 @@
package pp.mdga.client.Board;
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 pp.mdga.client.MdgaApp;
import java.util.ArrayList;
import java.util.List;
public class BoardView {
private static final float GRID_SIZE = 10.0f;
private static final float GRID_SIZE = 1.72f;
private static final float GRID_ELEVATION = 0.0f;
private static final int GRID_EXTEND = 11;
private static final String MAP_NAME = "circle_map.mdga";
private PileControl drawPile = new PileControl();
private PileControl discardPile = new PileControl();
private final MdgaApp app;
private PileControl drawPile = null;
private PileControl discardPile = null;
private ArrayList<NodeControl> infield = new ArrayList<NodeControl>(40);
private ArrayList<PieceControl> pieces;
BoardView(int playerCount) {
assert(2 <= playerCount && playerCount <= 4);
public BoardView(MdgaApp app) {
assert(app != null) : "app is null";
pieces = new ArrayList<PieceControl>(4 * playerCount);
this.app = app;
pieces = new ArrayList<PieceControl>(4 * 4);
initMap();
initCamera();
}
private void initCamera() {
app.getFlyByCamera().setEnabled(true);
int zoom = 20;
app.getCamera().setLocation(new Vector3f(zoom,0,zoom));
app.getCamera().lookAt(new Vector3f(0,0,0), new Vector3f(0,0,1));
DirectionalLight sun = new DirectionalLight();
sun.setColor(ColorRGBA.White);
sun.setDirection(new Vector3f(-1,0,-1));
app.getRootNode().addLight(sun);
AmbientLight ambient = new AmbientLight();
ambient.setColor(new ColorRGBA(0.3f,0.3f,0.3f,1));
app.getRootNode().addLight(ambient);
final int SHADOWMAP_SIZE= 1024 * 8;
DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(app.getAssetManager(), SHADOWMAP_SIZE, 4);
dlsr.setLight(sun);
app.getViewPort().addProcessor(dlsr);
}
private void initMap() {
List<AssetOnMap> assetsOnMap = MapLoader.loadMap(MAP_NAME);
for (AssetOnMap aom : assetsOnMap){
int x = aom.x();
int y = aom.y();
Vector3f pos = gridToWorld(x,y);
if(aom.boardAsset().name().contains("node")) {
infield.add(new NodeControl(app, pos, aom.boardAsset()));
} else {
Spatial model = createModel(aom.boardAsset());
model.setLocalTranslation(pos);
}
}
}
private Spatial createModel(BoardAsset boardAsset){
String modelName = boardAsset.getModelPath();
String texName = boardAsset.getDiffPath();
Spatial model = app.getAssetManager().loadModel(modelName);
model.scale(boardAsset.getSize());
model.rotate((float) Math.toRadians(0), 0, (float) Math.toRadians(90));
model.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
mat.setTexture("DiffuseMap", app.getAssetManager().loadTexture(texName));
model.setMaterial(mat);
app.getRootNode().attachChild(model);
return model;
}
private static Vector3f gridToWorld(int x, int y) {
assert(0 <= x && x < GRID_EXTEND);
assert(0 <= y && y < GRID_EXTEND);
return new Vector3f(GRID_SIZE * x, GRID_ELEVATION, GRID_SIZE * y);
return new Vector3f(GRID_SIZE * x, GRID_SIZE * y, GRID_ELEVATION);
}
}

View File

@@ -0,0 +1,66 @@
package pp.mdga.client.Board;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
class MapLoader {
static public List<AssetOnMap> loadMap(String mapName) {
List<AssetOnMap> assetsOnMap = new ArrayList<>();
try (InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(mapName);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
while (true) {
String entry = reader.readLine();
if(entry == null) break;
entry = entry.trim();
if(entry.isEmpty()) continue;
if(entry.charAt(0) == '#') continue;
String[] parts = entry.trim().split(" ");
assert(parts.length == 2) : "parts.lenghth != 2";
String assetName = parts[0];
String[] coordinates = parts[1].split(",");
assert(coordinates.length == 2) : "coordinates.lenghth != 2";
int x = Integer.parseInt(coordinates[0]);
int y = Integer.parseInt(coordinates[1]);
BoardAsset boardAsset = getLoadedAsset(assetName);
assetsOnMap.add(new AssetOnMap(boardAsset, x, y));
}
} catch (Exception e) {
e.printStackTrace();
}
return assetsOnMap;
}
static private BoardAsset getLoadedAsset(String assetName) {
return switch(assetName){
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 "tent_big" -> BoardAsset.bigTent;
case "tent_small" -> BoardAsset.smallTent;
case "stack" -> BoardAsset.cardStack;
case "jet" -> BoardAsset.jet;
case "radar" -> BoardAsset.radar;
case "ship" -> BoardAsset.ship;
case "tank" -> BoardAsset.tank;
default -> throw new IllegalStateException("Unexpected asset in .mdga file: " + assetName);
};
}
}

View File

@@ -1,5 +1,30 @@
package pp.mdga.client.Board;
public class NodeControl {
import com.jme3.material.Material;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Spatial;
import pp.mdga.client.MdgaApp;
class NodeControl {
private final MdgaApp app;
private Spatial model;
NodeControl(MdgaApp app, Vector3f pos, BoardAsset boardAsset) {
this.app = app;
String modelName = boardAsset.getModelPath();
String texName = boardAsset.getDiffPath();
Spatial model = app.getAssetManager().loadModel(modelName);
model.scale(boardAsset.getSize());
model.rotate((float) Math.toRadians(0), 0, (float) Math.toRadians(90));
model.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
mat.setTexture("DiffuseMap", app.getAssetManager().loadTexture(texName));
model.setMaterial(mat);
app.getRootNode().attachChild(model);
model.setLocalTranslation(pos);
}
}

View File

@@ -1,5 +1,5 @@
package pp.mdga.client.Board;
public class PieceControl {
class PieceControl {
}

View File

@@ -1,5 +1,5 @@
package pp.mdga.client.Board;
public class PileControl {
class PileControl {
}

View File

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

View File

@@ -0,0 +1,4 @@
package pp.mdga.client.Dialog;
public class InterruptDialog {
}

View File

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

View File

@@ -1,29 +1,31 @@
package pp.mdga.client;
import com.jme3.app.SimpleApplication;
import com.jme3.renderer.RenderManager;
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.RenderManager;
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.BoardView;
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();
@@ -32,62 +34,52 @@ public static void main(String[] args) {
@Override
public void simpleInitApp() {
animationHandler = new AnimationHandler(this);
acousticHandler = new AcousticHandler(this);
boardView = new BoardView(this);
dialogView = new DialogView(this);
flyCam.setEnabled(true);
int zoom = 20;
cam.setLocation(new Vector3f(zoom,0,zoom));
cam.lookAt(new Vector3f(0,0,0), new Vector3f(0,0,1));
//dialogView.mainMenu();
//acousticHandler.playState(MdgaState.GAME);
DirectionalLight sun = new DirectionalLight();
sun.setColor(ColorRGBA.White);
sun.setDirection(new Vector3f(-1,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);
createModel(Asset.lw).setLocalTranslation(new Vector3f(0,-10,0));
createModel(Asset.cir).setLocalTranslation(new Vector3f(0,-8,0));
createModel(Asset.marine).setLocalTranslation(new Vector3f(0,-6,0));
createModel(Asset.heer).setLocalTranslation(new Vector3f(0,-4,0));
createModel(Asset.node_normal).setLocalTranslation(new Vector3f(0,-2.5f,0));
createModel(Asset.node_home_blue).setLocalTranslation(new Vector3f(0,-1,0));
createModel(Asset.smallTent).setLocalTranslation(new Vector3f(0,1,0));
createModel(Asset.tank).setLocalTranslation(new Vector3f(0,5,0));
createModel(Asset.jet).setLocalTranslation(new Vector3f(0,12,0));
createModel(Asset.ship).setLocalTranslation(new Vector3f(0,17,0));
createModel(Asset.radar).setLocalTranslation(new Vector3f(0,20,0));
createModel(Asset.world);
System.out.println(Asset.node_normal.getModelPath());
System.out.println(Asset.node_normal.getDiffPath());
}
private Spatial createModel(Asset asset){
String modelName = asset.getModelPath();
String texName = asset.getDiffPath();
Spatial model = assetManager.loadModel(modelName);
model.scale(asset.getSize());
model.rotate((float) Math.toRadians(0), 0, (float) Math.toRadians(90));
model.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
mat.setTexture("DiffuseMap", assetManager.loadTexture(texName));
model.setMaterial(mat);
rootNode.attachChild(model);
return model;
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;
}
}

View File

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

View File

@@ -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<Notification> notifications = new ArrayList<>();
//TODO fetch model notifications
for (Notification n : notifications) {
state.handleNotification(app, n);
}
}
}

View File

@@ -1,5 +0,0 @@
package pp.mdga.client.State;
public class CeremonyState {
}

View File

@@ -1,5 +0,0 @@
package pp.mdga.client.State;
public class GameState {
}

View File

@@ -1,5 +0,0 @@
package pp.mdga.client.State;
public class LobbyState {
}

View File

@@ -1,5 +0,0 @@
package pp.mdga.client.State;
public class MdgaState {
}

View File

@@ -1,5 +0,0 @@
package pp.mdga.client.State;
public class MusicState {
}

View File

@@ -1,5 +0,0 @@
package pp.mdga.client.State;
public class SoundState {
}

View File

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

View File

@@ -0,0 +1,64 @@
world 0,0
#Nodes für Map
node_start -1,-5
node -1,-4
node -1,-3
node -1,-2
node_bonus -1,-1
node -2,-1
node -3,-1
node -4,-1
node -5,-1
node -5,0
node_start -5,1
node -4,1
node -3,1
node -2,1
node_bonus -1,1
node -1,2
node -1,3
node -1,4
node -1,5
node 0,5
node_start 1,5
node 1,4
node 1,3
node 1,2
node_bonus 1,1
node 2,1
node 3,1
node 4,1
node 5,1
node 5,0
node_start 5,-1
node 4,-1
node 3,-1
node 2,-1
node_bonus 1,-1
node 1,-2
node 1,-3
node 1,-4
node 1,-5
node 0,-5
#Node Home
node_home_blue 0,-1
node_home_blue 0,-2
node_home_blue 0,-3
node_home_blue 0,-4
node_home_black 0,1
node_home_black 0,2
node_home_black 0,3
node_home_black 0,4
node_home_yellow 1,0
node_home_yellow 2,0
node_home_yellow 3,0
node_home_yellow 4,0
node_home_green -1,0
node_home_green -2,0
node_home_green -3,0
node_home_green -4,0

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 KiB

View File

@@ -1,4 +0,0 @@
package pp.mdga.effect;
public interface Effect {
}

View File

@@ -6,7 +6,7 @@
* This class will be used to hold all Board relevant data.
*/
public class Board {
private Map<Color, Player> playerData;
private Map<Color, PlayerData> 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<Color, Player> getPlayerData() {
public Map<Color, PlayerData> getPlayerData() {
return playerData;
}

View File

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

View File

@@ -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 <Color, Player> players;
private Statistic gameStatistics;
private ArrayList<Card> drawPile;
private ArrayList<Card> discardPile = new ArrayList<>();
private ArrayList<BonusCard> drawPile;
private ArrayList<BonusCard> discardPile = new ArrayList<>();
private Board board;
private Color activeColor;
private LinkedList<Color> 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<Color, Player> getPlayers() {
return players;
}
/**
* This method sets the players.
*
* @param players the new players
*/
public void setPlayers(Map<Color, Player> 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<BonusCard> getDrawPile() {
return drawPile;
}
/**
* This method sets the draw pile.
*
* @param drawPile the new draw pile
*/
public void setDrawPile(ArrayList<BonusCard> drawPile) {
this.drawPile = drawPile;
}
/**
* This method returns the discard pile.
*
* @return the discard pile
*/
public ArrayList<BonusCard> getDiscardPile() {
return discardPile;
}
/**
* This method sets the discard pile.
*
* @param discardPile the new discard pile
*/
public void setDiscardPile(ArrayList<BonusCard> 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<Color> getOrder() {
return order;
}
/**
* This method sets the order of the players.
*
* @param order the new order of the players
*/
public void setOrder(LinkedList<Color> order) {
this.order = order;
}
/**
* This method returns the player connection ID.
*
* @return the player connection ID
*/
public Map<Color, Integer> getPlayerConnectionID() {
return playerConnectionID;
}
/**
* This method sets the player connection ID.
*
* @param playerConnectionID the new player connection ID
*/
public void setPlayerConnectionID(Map<Color, Integer> 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);
}
}

View File

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

View File

@@ -9,7 +9,7 @@ public class Player {
private String name;
private Statistic playerStatistic;
private ArrayList<Card> handCards;
private ArrayList<BonusCard> handCards;
private final int id;
/**
@@ -53,17 +53,17 @@ public Statistic getPlayerStatistic() {
*
* @return the handCards of the player
*/
public ArrayList<Card> getHandCards() {
public ArrayList<BonusCard> 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);
}

View File

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

View File

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

View File

@@ -0,0 +1,9 @@
package pp.mdga.notification;
import pp.mdga.game.Color;
public class ActivePlayerNotification extends Notification {
ActivePlayerNotification(Color color) {
}
}

View File

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

View File

@@ -0,0 +1,9 @@
package pp.mdga.notification;
import pp.mdga.game.Color;
public class InterruptNotification extends Notification {
InterruptNotification(Color color) {
}
}

View File

@@ -0,0 +1,9 @@
package pp.mdga.notification;
import pp.mdga.game.Color;
public class MovePieceNotification extends Notification {
MovePieceNotification(Color color, int nodeIndex) {
}
}

View File

@@ -0,0 +1,4 @@
package pp.mdga.notification;
public abstract class Notification {
}

View File

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

View File

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

View File

@@ -0,0 +1,9 @@
package pp.mdga.notification;
import pp.mdga.game.Color;
public class PlayerInGameNotification extends Notification {
PlayerInGameNotification(Color color, String name) {
}
}

View File

@@ -0,0 +1,9 @@
package pp.mdga.notification;
import pp.mdga.game.Color;
public class ResumeNotification extends Notification {
ResumeNotification(Color color) {
}
}

View File

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

View File

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

View File

@@ -34,6 +34,3 @@
}
include 'mdga:client'
findProject(':mdga:client')?.name = 'client'
include 'mdga:client'
findProject(':mdga:client')?.name = 'client'