Merge branch 'dev/client_beck' into development

# Conflicts:
#	Projekte/mdga/client/src/main/java/pp/mdga/client/Asset.java
#	Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java
#	Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/AcousticHandler.java
#	Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/MdgaSound.java
#	Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/SoundAsset.java
#	Projekte/mdga/client/src/main/java/pp/mdga/client/animation/JetAnimation.java
#	Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java
#	Projekte/mdga/model/src/main/java/pp/mdga/client/gamestate/GameStates.java
This commit is contained in:
Felix Koppe
2024-12-07 15:00:27 +01:00
36 changed files with 880030 additions and 66 deletions

View File

@@ -40,6 +40,12 @@ public enum Asset {
shieldSymbol("Models/shieldCard/shieldSymbol.j3o", "Models/shieldCard/shieldCard_diff.png"),
dice,
missile("Models/missile/AVMT300.obj", "Models/missile/texture.jpg", 0.1f),
dice,
tankShoot("Models/tank/tank_shoot_bot.obj", "Models/tank/tank_diff.png"),
tankShootTop("Models/tank/tank_shoot_top.obj", "Models/tank/tank_diff.png"),
treesSmallBackground("Models/treeSmall/small_trees_background.obj", "Models/treeSmall/treeSmall_diff.png", 1.2f),
treesBigBackground("Models/treeBig/big_trees_background.obj", "Models/treeBig/treeBig_diff.png", 1.2f),
shell
;
private final String modelPath;

View File

@@ -155,7 +155,7 @@ private void handleGame(Notification notification) {
}
guiHandler.hideText();
} else if (notification instanceof ThrowPieceNotification n) {
boardHandler.throwBombAnim(n.getPieceId());
boardHandler.throwPiece(n.getPieceId(), n.getThrowColor());
} else if (notification instanceof NoShieldNotification n) {
boardHandler.unshieldPiece(n.getPieceId());
} else if (notification instanceof PlayCardNotification n) {

View File

@@ -0,0 +1,47 @@
package pp.mdga.client;
import com.jme3.math.Vector3f;
public class Util {
private Util(){}
/**
* Performs linear interpolation between two values.
*
* @param start The starting value.
* @param end The ending value.
* @param t A parameter between 0 and 1 representing the interpolation progress.
* @return The interpolated value.
*/
public static float linInt(float start, float end, float t) {
return start + t * (end - start);
}
/**
* Performs quadratic interpolation between three points.
*
* @param p1 The initial point.
* @param p2 The middle point.
* @param p3 The final point.
* @param t The interpolation parameter (0 <= t <= 1).
* @return The interpolated point.
*/
public static Vector3f quadInt(Vector3f p1, Vector3f p2, Vector3f p3, float t) {
// Quadratic interpolation: (1-t)^2 * p1 + 2 * (1-t) * t * p2 + t^2 * p3
float oneMinusT = 1 - t;
return p1.mult(oneMinusT * oneMinusT)
.add(p2.mult(2 * oneMinusT * t))
.add(p3.mult(t * t));
}
/**
* A smooth ease-in-out function for interpolation.
* It accelerates and decelerates the interpolation for a smoother effect.
*
* @param x The interpolation parameter (0 <= x <= 1).
* @return The adjusted interpolation value.
*/
public static float easeInOut(float x){
return x < 0.5 ? 4 * x * x * x : (float) (1 - Math.pow(-2 * x + 2, 3) / 2);
}
}

View File

@@ -138,6 +138,15 @@ public void playSound(MdgaSound sound) {
case MATRIX:
assets.add(new SoundAssetDelayVolume(SoundAsset.MATRIX, 1.0f, 0.0f));
break;
case TURRET_ROTATE:
assets.add(new SoundAssetDelayVolume(SoundAsset.TURRET_ROTATE, 0.7f, 0f));
break;
case TANK_SHOOT:
assets.add(new SoundAssetDelayVolume(SoundAsset.TANK_SHOOT, 0.7f, 0f));
break;
case TANK_EXPLOSION:
assets.add(new SoundAssetDelayVolume(SoundAsset.EXPLOSION_1, 1.0f, 0f));
break;
default:
break;
}
@@ -261,6 +270,12 @@ private void updateVolumeAndTrack() {
} else if (playing != null) {
// Update volume for the currently playing track
playing.update(getMusicVolumeTotal());
} else if (scheduled != null) {
// If no track is playing and one is scheduled, start it immediately at full volume
playing = scheduled;
scheduled = null;
playing.play();
playing.update(getMusicVolumeTotal()); // Set volume to full
}
}

View File

@@ -38,4 +38,7 @@ public enum MdgaSound {
UI90,
MISSILE,
MATRIX,
TURRET_ROTATE,
TANK_SHOOT,
TANK_EXPLOSION
}

View File

@@ -38,6 +38,11 @@ enum SoundAsset {
MISSILE("missile.ogg"),
MATRIX("matrix.wav"),
CONNECTED("connected.wav");
CONNECTED("connected.wav"),
TURRET_ROTATE("turret_rotate.ogg"),
TANK_SHOOT("tank_shoot.ogg")
;
private final String path;

View File

@@ -0,0 +1,18 @@
package pp.mdga.client.animation;
import pp.mdga.client.InitControl;
public class ActionControl extends InitControl {
private final Runnable runnable;
public ActionControl(Runnable runnable){
this.runnable = runnable;
}
protected void action(){
if(runnable == null) throw new RuntimeException("runnable is null");
else runnable.run();
}
}

View File

@@ -0,0 +1,70 @@
package pp.mdga.client.animation;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Geometry;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import pp.mdga.client.InitControl;
import static pp.mdga.client.Util.linInt;
public class FadeControl extends ActionControl {
private float duration; // Duration of the fade effect
private float timeElapsed = 0;
private boolean init = false;
private float startAlpha;
private float endAlpha;
public FadeControl(float duration, float startAlpha, float endAlpha, Runnable actionAfter) {
super(actionAfter);
this.duration = duration;
this.startAlpha = startAlpha;
this.endAlpha = endAlpha;
}
public FadeControl(float duration, float startAlpha, float endAlpha) {
this(duration, startAlpha, endAlpha, null);
}
@Override
protected void initSpatial() {
init = true;
}
@Override
protected void controlUpdate(float tpf) {
if (!init) return;
timeElapsed += tpf;
float t = timeElapsed / duration; // Calculate progress (0 to 1)
if (t >= 1) {
// Fade complete
t = 1;
init = false;
spatial.removeControl(this);
action();
}
float alpha = linInt(startAlpha, endAlpha, t); // Interpolate alpha
// Update the material's alpha
if (spatial instanceof Geometry geometry) {
Material mat = geometry.getMaterial();
if (mat != null) {
ColorRGBA diffuse = (ColorRGBA) mat.getParam("Diffuse").getValue();
mat.setColor("Diffuse", new ColorRGBA(diffuse.r, diffuse.g, diffuse.b, alpha));
ColorRGBA ambient = (ColorRGBA) mat.getParam("Ambient").getValue();
mat.setColor("Ambient", new ColorRGBA(ambient.r, ambient.g, ambient.b, alpha));
// Disable shadows when the object is nearly invisible
if (alpha <= 0.1f) {
geometry.setShadowMode(RenderQueue.ShadowMode.Off);
} else {
geometry.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
}
} else throw new RuntimeException("Material is null");
} else throw new RuntimeException("Spatial is not instance of Geometry");
}
}

View File

@@ -34,6 +34,7 @@ public class JetAnimation {
private final float animationDuration;
private Explosion explosion;
private final UUID id;
private Runnable actionAfter;
/**
* Constructor for the {@code JetAnimation} class.
@@ -45,7 +46,7 @@ public class JetAnimation {
* @param curveHeight The height of the curve for the jet's flight path.
* @param animationDuration The total duration of the jet animation.
*/
public JetAnimation(MdgaApp app, Node rootNode, UUID uuid, Vector3f targetPoint, float curveHeight, float animationDuration) {
public JetAnimation(MdgaApp app, Node rootNode, UUID uuid, Vector3f targetPoint, float curveHeight, float animationDuration, Runnable actionAfter) {
Vector3f spawnPoint = targetPoint.add(170, 50, 50);
Vector3f controlPoint = targetPoint.add(new Vector3f(0, 0, -45));
@@ -62,7 +63,8 @@ public JetAnimation(MdgaApp app, Node rootNode, UUID uuid, Vector3f targetPoint,
id = uuid;
explosion = new Explosion(app, rootNode, targetPoint);
explosion = new Explosion(app, rootNode, nodePoint);
this.actionAfter = actionAfter;
}
/**
@@ -124,10 +126,7 @@ protected void controlUpdate(float tpf) {
}
if (elapsedTime > 6.0f) {
GameView gameView = (GameView) app.getView();
BoardHandler boardHandler = gameView.getBoardHandler();
boardHandler.throwPieceAnim(id);
endAnim();
}
}
@@ -136,6 +135,10 @@ protected void controlRender(RenderManager rm, ViewPort vp) {}
});
}
private void endAnim(){
actionAfter.run();
}
/**
* The {@code BezierCurve3f} class represents a 3D cubic Bezier curve.
* It provides methods to interpolate positions and derivatives along the curve.

View File

@@ -0,0 +1,200 @@
package pp.mdga.client.animation;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh.Type;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import pp.mdga.client.InitControl;
import pp.mdga.client.MdgaApp;
import pp.mdga.client.acoustic.MdgaSound;
import java.util.*;
public class MatrixAnimation extends ActionControl {
private MdgaApp app;
private static final Random RANDOM = new Random();
private Vector3f radarPos;
private Runnable runnable;
private boolean init = false;
private List<ParticleEmitter> activeEmitter = new ArrayList<>();
private ParticleEmitter radarEmitter = null;
private float timeElapsed = 0f;
private enum MatrixState{
RADAR_ON,
RADAR_OFF,
MATRIX_ON,
MATRIX_OFF
}
private MatrixState state;
public MatrixAnimation(MdgaApp app, Vector3f radarPos, Runnable runnable){
super(runnable);
this.app = app;
this.radarPos = radarPos;
}
@Override
protected void initSpatial() {
state = MatrixState.RADAR_ON;
timeElapsed = 0;
init = true;
radar();
}
@Override
protected void controlUpdate(float tpf) {
if(!init) return;
timeElapsed += tpf;
switch(state){
case RADAR_ON -> {
if(timeElapsed >= 2f){
state = MatrixState.RADAR_OFF;
timeElapsed = 0;
radarEmitter.setParticlesPerSec(0);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
app.getRootNode().detachChild(radarEmitter);
}
}, 3000);
}
}
case RADAR_OFF -> {
if(timeElapsed >= 0.1f){
state = MatrixState.MATRIX_ON;
timeElapsed = 0;
matrix();
}
}
case MATRIX_ON -> {
if(timeElapsed >= 3f){
state = MatrixState.MATRIX_OFF;
timeElapsed = 0;
turnOff();
new Timer().schedule(new TimerTask() {
@Override
public void run() {
for (ParticleEmitter particleEmitter : activeEmitter){
app.getRootNode().detachChild(particleEmitter);
}
}
}, 3000);
}
}
case MATRIX_OFF -> {
if(timeElapsed >= 0.5f){
init = false;
spatial.removeControl(this);
action();
}
}
}
}
private void turnOff(){
for (ParticleEmitter particleEmitter : activeEmitter){
particleEmitter.setParticlesPerSec(0f);
}
}
private void radar(){
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Particle.j3md");
mat.setTexture("Texture", app.getAssetManager().loadTexture("Images/particle/radar_beam.png"));
ParticleEmitter emitter = new ParticleEmitter("Effect", Type.Triangle, 50);
emitter.setMaterial(mat);
emitter.setImagesX(1); // columns
emitter.setImagesY(1); // rows
emitter.setSelectRandomImage(true);
emitter.setStartColor(ColorRGBA.White);
emitter.setEndColor(ColorRGBA.Black);
emitter.getParticleInfluencer().setInitialVelocity(new Vector3f(0f, 0f, 2));
emitter.getParticleInfluencer().setVelocityVariation(0f);
emitter.setStartSize(0.1f);
emitter.setEndSize(10);
emitter.setGravity(0, 0, 0);
float life = 2.6f;
emitter.setLowLife(life);
emitter.setHighLife(life);
emitter.setLocalTranslation(radarPos.add(new Vector3f(0,0,5)));
emitter.setParticlesPerSec(1.8f);
app.getRootNode().attachChild(emitter);
radarEmitter = emitter;
}
private void matrix(){
for(int i = 0; i < 5; i++){
particleStream(
generateMatrixColor(),
generateMatrixColor(),
getRandomFloat(0,1f),
getRandomPosition(),
getRandomFloat(1,2)
);
}
}
private void particleStream(ColorRGBA start, ColorRGBA end, float speedVar, Vector3f pos, float spawnVar){
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Particle.j3md");
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
mat.setTexture("Texture", app.getAssetManager().loadTexture("Images/particle/particle_cir.png"));
ParticleEmitter matrix = new ParticleEmitter("Effect", Type.Triangle, 50);
matrix.setMaterial(mat);
matrix.setImagesX(2); // columns
matrix.setImagesY(1); // rows
matrix.setSelectRandomImage(true);
matrix.setStartColor(start);
matrix.setEndColor(end);
matrix.getParticleInfluencer().setInitialVelocity(new Vector3f(0f, 0f, -6f - speedVar));
matrix.getParticleInfluencer().setVelocityVariation(0f);
matrix.setStartSize(0.4f);
matrix.setEndSize(0.6f);
matrix.setGravity(0, 0, 2f);
matrix.setLowLife(3f);
matrix.setHighLife(3f);
matrix.setLocalTranslation(spatial.getLocalTranslation().add(pos).add(new Vector3f(0,0,15)));
matrix.setParticlesPerSec(spawnVar);
app.getRootNode().attachChild(matrix);
activeEmitter.add(matrix);
}
public static Vector3f getRandomPosition() {
// Generate a random angle in radians (0 to 2π)
float angle = (float) (2 * Math.PI * RANDOM.nextDouble());
// Generate a random radius with uniform distribution
float radius = (float) Math.sqrt(RANDOM.nextDouble());
radius *= 1f;
// Convert polar coordinates to Cartesian
float x = radius * (float) Math.cos(angle);
float y = radius * (float) Math.sin(angle);
return new Vector3f(x,y,0);
}
public static float getRandomFloat(float start, float end) {
if (start > end) {
throw new IllegalArgumentException("Start must be less than or equal to end.");
}
return start + RANDOM.nextFloat() * (end - start);
}
public static ColorRGBA generateMatrixColor() {
// Red is dominant
float red = 0.8f + RANDOM.nextFloat() * 0.2f; // Red channel: 0.8 to 1.0
// Green is moderately high
float green = 0.4f + RANDOM.nextFloat() * 0.3f; // Green channel: 0.4 to 0.7
// Blue is minimal
float blue = RANDOM.nextFloat() * 0.2f; // Blue channel: 0.0 to 0.2
float alpha = 1.0f; // Fully opaque
return new ColorRGBA(red, green, blue, alpha);
}
}

View File

@@ -1,7 +1,8 @@
package pp.mdga.client.animation;
import com.jme3.math.Vector3f;
import pp.mdga.client.InitControl;
import static pp.mdga.client.Util.*;
/**
* A control that smoothly moves a spatial from an initial position to an end position
@@ -12,16 +13,16 @@
* an ease-in-out curve to create a smooth start and stop effect.
* </p>
*/
public class MoveControl extends InitControl {
public class MoveControl extends ActionControl {
private boolean moving;
private final Vector3f initPos;
private final Vector3f endPos;
private final Vector3f middlePos;
private final static float HEIGHT = 2;
private final static float MOVE_SPEED = 1f;
private float progress = 0;
private final Runnable actionAfter;
private final float height;
private final float duration;
private float timer = 0;
private boolean easing;
/**
* Creates a new MoveControl with specified initial and end positions, and an action to run after the movement.
@@ -32,15 +33,22 @@ public class MoveControl extends InitControl {
* @param actionAfter A Runnable that will be executed after the movement finishes.
*/
public MoveControl(Vector3f initPos, Vector3f endPos, Runnable actionAfter){
this(initPos, endPos, actionAfter, 2, 1, true);
}
public MoveControl(Vector3f initPos, Vector3f endPos, Runnable actionAfter, float height, float duration, boolean easing){
super(actionAfter);
moving = false;
this.initPos = initPos;
this.endPos = endPos;
this.height = height;
this.duration = duration;
this.easing = easing;
middlePos = new Vector3f(
(initPos.x + endPos.x) / 2,
(initPos.y + endPos.y) / 2,
HEIGHT
(initPos.x + endPos.x) / 2,
(initPos.y + endPos.y) / 2,
height
);
this.actionAfter = actionAfter;
}
/**
@@ -50,7 +58,7 @@ public MoveControl(Vector3f initPos, Vector3f endPos, Runnable actionAfter){
@Override
protected void initSpatial() {
moving = true;
progress = 0;
timer = 0;
}
/**
@@ -63,10 +71,16 @@ protected void initSpatial() {
@Override
protected void controlUpdate(float tpf) {
if(!moving) return;
progress += tpf * MOVE_SPEED;
if(progress > 1) progress = 1;
spatial.setLocalTranslation(quadInt(initPos,middlePos,endPos, easeInOut(progress)));
if(progress == 1) end();
timer += tpf;
float t = timer / duration;
if (t >= 1) t = 1;
float interpolated = easing ? easeInOut(t) : t;
spatial.setLocalTranslation(quadInt(initPos,middlePos,endPos, interpolated));
if(t >= 1) end();
}
/**
@@ -75,35 +89,11 @@ protected void controlUpdate(float tpf) {
*/
private void end(){
moving = false;
actionAfter.run();
spatial.removeControl(this);
action();
}
/**
* Performs quadratic interpolation between three points.
*
* @param p1 The initial point.
* @param p2 The middle point.
* @param p3 The final point.
* @param t The interpolation parameter (0 <= t <= 1).
* @return The interpolated point.
*/
private Vector3f quadInt(Vector3f p1, Vector3f p2, Vector3f p3, float t) {
// Quadratic interpolation: (1-t)^2 * p1 + 2 * (1-t) * t * p2 + t^2 * p3
float oneMinusT = 1 - t;
return p1.mult(oneMinusT * oneMinusT)
.add(p2.mult(2 * oneMinusT * t))
.add(p3.mult(t * t));
}
/**
* A smooth ease-in-out function for interpolation.
* It accelerates and decelerates the interpolation for a smoother effect.
*
* @param x The interpolation parameter (0 <= x <= 1).
* @return The adjusted interpolation value.
*/
private float easeInOut(float x){
return x < 0.5 ? 4 * x * x * x : (float) (1 - Math.pow(-2 * x + 2, 3) / 2);
}
}

View File

@@ -0,0 +1,167 @@
package pp.mdga.client.animation;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import pp.mdga.client.Asset;
import pp.mdga.client.InitControl;
import pp.mdga.client.MdgaApp;
import pp.mdga.client.acoustic.MdgaSound;
import pp.mdga.client.board.TankTopControl;
import java.util.Timer;
import java.util.TimerTask;
import static com.jme3.material.Materials.LIGHTING;
import static com.jme3.material.Materials.UNSHADED;
public class ShellAnimation extends ActionControl {
private static final float FLYING_DURATION = 1.25f;
private static final float FLYING_HEIGHT = 12f;
private TankTopControl tankTopControl;
private MdgaApp app;
public ShellAnimation(TankTopControl tankTopControl, MdgaApp app, Runnable actionAfter){
super(actionAfter);
this.tankTopControl = tankTopControl;
this.app = app;
}
@Override
protected void initSpatial() {
tankTopControl.rotate(spatial.getLocalTranslation(), this::shoot);
app.getAcousticHandler().playSound(MdgaSound.TURRET_ROTATE);
app.getRootNode().attachChild(createShell());
}
private Vector3f getShootPos(){
Vector3f localOffset = new Vector3f(0, -5.4f, 2.9f);
Quaternion turretRotation = tankTopControl.getSpatial().getLocalRotation();
Vector3f transformedOffset = turretRotation.mult(localOffset);
return tankTopControl.getSpatial().getLocalTranslation().add(transformedOffset);
}
private void shoot(){
app.getAcousticHandler().playSound(MdgaSound.TANK_SHOOT);
Vector3f shootPos = getShootPos();
createEffect(
shootPos,
"Images/particle/flame.png",
2, 2,
1, 3,
1f,
0.3f, 0.7f,
new ColorRGBA(1f, 0.8f, 0.4f, 0.5f),
new ColorRGBA(1f, 0f, 0f, 0f)
);
createEffect(
shootPos,
"Images/particle/vapor_cloud.png",
3, 3,
0.3f, 0.8f,
10,
0.1f, 0.35f,
new ColorRGBA(0.5f,0.5f,0.5f,0.5f),
ColorRGBA.Black
);
Spatial shell = createShell();
app.getRootNode().attachChild(shell);
shell.addControl(new ShellControl(this::hitExplosion, shootPos, spatial.getLocalTranslation(), FLYING_HEIGHT, FLYING_DURATION, app.getAssetManager()));
}
private Spatial createShell(){
Spatial model = app.getAssetManager().loadModel(Asset.shell.getModelPath());
model.scale(.16f);
model.setLocalTranslation(tankTopControl.getSpatial().getLocalTranslation());
Vector3f shootPos = tankTopControl.getSpatial().getLocalTranslation();
Vector3f targetPos = spatial.getLocalTranslation();
Vector3f direction = targetPos.subtract(shootPos).normalize();
Quaternion rotation = new Quaternion();
rotation.lookAt(direction, new Vector3f(1,0,0)); // Assuming UNIT_Y is the up vector
model.setLocalRotation(rotation);
model.rotate(FastMath.HALF_PI,0,0);
Material mat = new Material(app.getAssetManager(), LIGHTING);
mat.setBoolean("UseMaterialColors", true);
ColorRGBA color = ColorRGBA.fromRGBA255(143,117,0,255);
mat.setColor("Diffuse", color);
mat.setColor("Ambient", color);
model.setMaterial(mat);
return model;
}
private void hitExplosion(){
app.getAcousticHandler().playSound(MdgaSound.TANK_EXPLOSION);
createEffect(
spatial.getLocalTranslation().setZ(1),
"Images/particle/flame.png",
2, 2,
1, 5,
2f,
0.3f, 0.7f,
new ColorRGBA(1f, 0.8f, 0.4f, 0.5f),
new ColorRGBA(1f, 0f, 0f, 0f)
);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
action();
}
}, 800);
}
private void createEffect(Vector3f shootPos,
String image,
int x, int y,
float startSize, float endSize,
float velocity,
float lowLife, float highLife,
ColorRGBA start, ColorRGBA end){
// Create a particle emitter for the explosion
ParticleEmitter explosionEmitter = new ParticleEmitter("Explosion", ParticleMesh.Type.Triangle, 100);
Material explosionMat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Particle.j3md");
explosionMat.setTexture("Texture", app.getAssetManager().loadTexture(image));
explosionEmitter.setMaterial(explosionMat);
// Particle properties
explosionEmitter.setImagesX(x); // Columns in the texture
explosionEmitter.setImagesY(y); // Rows in the texture
explosionEmitter.setSelectRandomImage(true); // Randomize images for variety
explosionEmitter.setStartColor(start); // Bright yellowish orange
explosionEmitter.setEndColor(end); // Fade to transparent red
explosionEmitter.setStartSize(startSize); // Initial size
explosionEmitter.setEndSize(endSize); // Final size
explosionEmitter.setLowLife(lowLife); // Minimum lifetime of particles
explosionEmitter.setHighLife(highLife); // Maximum lifetime of particles
explosionEmitter.setGravity(0, 0, 1); // Gravity to pull particles down
explosionEmitter.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 0, velocity));
explosionEmitter.getParticleInfluencer().setVelocityVariation(1f); // Adds randomness to the initial velocity
explosionEmitter.setFacingVelocity(true); // Particles face their velocity direction
explosionEmitter.setLocalTranslation(shootPos);
explosionEmitter.setParticlesPerSec(0);
explosionEmitter.emitAllParticles();
app.getRootNode().attachChild(explosionEmitter);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
app.getRootNode().detachChild(explosionEmitter);
}
}, 1000);
}
}

View File

@@ -0,0 +1,89 @@
package pp.mdga.client.animation;
import com.jme3.asset.AssetManager;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import pp.mdga.client.InitControl;
public class ShellControl extends ActionControl {
private final Vector3f shootPos;
private final Vector3f endPos;
private final float height;
private final float duration;
private Vector3f oldPos;
private ParticleEmitter emitter;
private AssetManager assetManager;
public ShellControl(Runnable runnable, Vector3f shootPos, Vector3f endPos, float height, float duration, AssetManager assetManager){
super(runnable);
this.shootPos = shootPos;
this.endPos = endPos;
this.height = height;
this.duration = duration;
this.assetManager = assetManager;
}
@Override
protected void initSpatial() {
spatial.addControl(new MoveControl(
shootPos,
endPos,
()->{
emitter.killAllParticles();
emitter.setParticlesPerSec(0);
emitter.removeFromParent();
spatial.removeControl(this);
spatial.removeFromParent();
action();
},
height,
duration,
false
));
oldPos = spatial.getLocalTranslation().clone();
createEmitter();
}
private void createEmitter() {
emitter = new ParticleEmitter("ShellTrail", ParticleMesh.Type.Triangle, 200);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
mat.setTexture("Texture", assetManager.loadTexture("Images/particle/line.png")); // Nutze eine schmale, linienartige Textur
emitter.setMaterial(mat);
// Comic-Style Farben
emitter.setStartColor(new ColorRGBA(1f, 1f, 1f, 1f)); // Reinweiß
emitter.setEndColor(new ColorRGBA(1f, 1f, 1f, 0f)); // Transparent
// Partikelgröße und Lebensdauer
emitter.setStartSize(0.15f); // Startgröße
emitter.setEndSize(0.1f); // Endgröße
emitter.setLowLife(0.14f); // Sehr kurze Lebensdauer
emitter.setHighLife(0.14f);
emitter.setGravity(0, 0, 0); // Keine Gravitation
emitter.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 0, 0));
emitter.getParticleInfluencer().setVelocityVariation(0f); // Kein Variationsspielraum
// Hohe Dichte für eine glatte Spur
emitter.setParticlesPerSec(500);
// Zur Shell hinzufügen
spatial.getParent().attachChild(emitter);
}
@Override
protected void controlUpdate(float tpf) {
Vector3f direction = spatial.getLocalTranslation().subtract(oldPos).normalize();
if (direction.lengthSquared() > 0) {
spatial.getLocalRotation().lookAt(direction, Vector3f.UNIT_X);
spatial.rotate(FastMath.HALF_PI,0,0);
}
oldPos = spatial.getLocalTranslation().clone();
emitter.setLocalTranslation(spatial.getLocalTranslation().clone());
}
}

View File

@@ -1,6 +1,9 @@
package pp.mdga.client.board;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.renderer.queue.RenderQueue;
@@ -56,6 +59,10 @@ public class BoardHandler {
private PieceControl selectedOwnPiece;
private PieceControl selectedEnemyPiece;
private DiceControl diceControl;
//Radar Position for Matrix animation
private Vector3f radarPos;
//TankTop for shellAnimation
private TankTopControl tankTop;
/**
* Creates a new BoardHandler.
@@ -148,12 +155,24 @@ private void initMap() {
case node_wait_blue -> addHomeNode(waitingNodesMap, Color.NAVY, assetOnMap);
case node_wait_green -> addHomeNode(waitingNodesMap, Color.ARMY, assetOnMap);
case node_wait_yellow -> addHomeNode(waitingNodesMap, Color.CYBER, assetOnMap);
case radar -> addRadar(assetOnMap);
case tankShoot -> addTankShoot(assetOnMap);
default -> displayAsset(assetOnMap);
}
}
}
private void addTankShoot(AssetOnMap assetOnMap) {
displayAsset(assetOnMap);
tankTop = displayAndControl(new AssetOnMap(Asset.tankShootTop, assetOnMap.x(), assetOnMap.y(), assetOnMap.rot()), new TankTopControl());
}
private void addRadar(AssetOnMap assetOnMap) {
radarPos = gridToWorld(assetOnMap.x(), assetOnMap.y());
displayAsset(assetOnMap);
}
/**
* Converts an asset to its corresponding color.
*
@@ -187,11 +206,16 @@ private Spatial createModel(Asset asset, Vector3f pos, float rot) {
model.rotate((float) Math.toRadians(0), 0, (float) Math.toRadians(rot));
model.setLocalTranslation(pos);
model.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
mat.setTexture("DiffuseMap", app.getAssetManager().loadTexture(texName));
mat.setBoolean("UseMaterialColors", true); // Required for Material Colors
mat.setColor("Diffuse", new ColorRGBA(1, 1, 1, 1)); // White color with full alpha
mat.setColor("Ambient", new ColorRGBA(1, 1, 1, 1)); // Ambient color with full alpha
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
model.setMaterial(mat);
rootNodeBoard.attachChild(model);
rootNodeBoard.attachChild(model);
return model;
}
@@ -770,34 +794,57 @@ public void movePieceStartAnim(UUID uuid, int moveIndex){
*/
public void throwPieceAnim(UUID uuid){
pieces.get(uuid).getSpatial().addControl(new MoveControl(
pieces.get(uuid).getLocation(), getNextWaitingNode(pieceColor.get(uuid)).getLocation(), ()->throwPiece(uuid))
pieces.get(uuid).getLocation(), getNextWaitingNode(pieceColor.get(uuid)).getLocation(),
()->throwPiece(uuid))
);
}
/**
* Animates the throwing of a piece to the next available waiting node and plays jet animation.
*
* @param uuid the UUID of the piece to animate
*/
public void throwBombAnim(UUID uuid){
Vector3f targetPoint = pieces.get(uuid).getLocation();
JetAnimation anim = new JetAnimation(app, rootNode, uuid, targetPoint, 40, 6);
anim.start();
public void throwPiece(UUID uuid, Color throwColor){
switch(throwColor){
case ARMY -> throwShell(uuid);
case NAVY -> throwMissle(uuid);
case CYBER -> throwMatrix(uuid);
case AIRFORCE -> throwBomb(uuid);
default -> throw new RuntimeException("invalid color");
}
}
/**
* Animates the throwing of a piece to the next available waiting node and plays ship animation.
* Animates the throwing of a piece to the next available waiting node.
*
* @param uuid the UUID of the piece to animate
*/
public void throwMissileAnim(UUID uuid){
private void throwBomb(UUID uuid) {
Vector3f targetPoint = pieces.get(uuid).getLocation();
JetAnimation anim = new JetAnimation(app, rootNode, uuid, targetPoint, 40, 6, ()->throwPieceAnim(uuid));
anim.start();
}
private void throwMatrix(UUID uuid) {
//app.getAcousticHandler().playSound(MdgaSound.MATRIX);
Spatial piece = pieces.get(uuid).getSpatial();
piece.addControl(new MatrixAnimation(app, radarPos,()-> {
piece.addControl(new FadeControl(1,1,0,
() -> {
throwPiece(uuid);
piece.addControl(new FadeControl(1,0,1));
}
));
}));
}
private void throwMissle(UUID uuid) {
Vector3f targetPoint = pieces.get(uuid).getLocation();
MissileAnimation anim = new MissileAnimation(app, rootNode, uuid, targetPoint, 2);
anim.start();
}
private void throwShell(UUID uuid) {
pieces.get(uuid).getSpatial().addControl(new ShellAnimation(tankTop, app, ()-> throwPieceAnim(uuid)));
}
/**
* Animates the swapping of two pieces by swapping their positions and rotations.
*

View File

@@ -109,6 +109,9 @@ private static Asset getLoadedAsset(String assetName) {
case "tank" -> Asset.tank;
case "treeSmall" -> Asset.treeSmall;
case "treeBig" -> Asset.treeBig;
case "tank_shoot" -> Asset.tankShoot;
case "treesBigBackground" -> Asset.treesBigBackground;
case "treesSmallBackground" -> Asset.treesSmallBackground;
default -> throw new IllegalStateException("Unexpected value: " + assetName);
};
}

View File

@@ -141,7 +141,7 @@ public void initSpatial(){
}
public void rotateInit() {
// rotate(rotation - initRotation);
setRotation(initRotation);
}
/**
@@ -278,4 +278,5 @@ public boolean isSelectable() {
public void setHoverable(boolean hoverable) {
this.hoverable = hoverable;
}
}

View File

@@ -0,0 +1,105 @@
package pp.mdga.client.board;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import pp.mdga.client.InitControl;
import static pp.mdga.client.Util.linInt;
public class TankTopControl extends InitControl {
private float timer = 0; // Time elapsed
private final static float DURATION = 1.5f; // Total rotation duration in seconds
private boolean rotating = false; // Flag to track if rotation is active
private float startAngle = 0;
private float endAngle = 0;
private Runnable actionAfter = null;
@Override
protected void controlUpdate(float tpf) {
if (!rotating) return;
// Update the timer
timer += tpf;
// Calculate interpolation factor (0 to 1)
float t = timer / DURATION;
if (t >= 1) t = 1;
float curAngle = linInt(startAngle, endAngle, t);
// Interpolate the rotation
Quaternion interpolatedRotation = new Quaternion();
interpolatedRotation.fromAngleAxis((float) Math.toRadians(curAngle), Vector3f.UNIT_Z);
// Apply the interpolated rotation to the spatial
spatial.setLocalRotation(interpolatedRotation);
if(t >= 1){
rotating = false;
if(actionAfter != null) actionAfter.run();
}
}
public void rotate(Vector3f enemyPos, Runnable actionAfter) {
if (spatial == null) throw new RuntimeException("spatial is null");
startAngle = getOwnAngle();
endAngle = getEnemyAngle(enemyPos);
// Adjust endAngle to ensure the shortest path
float deltaAngle = endAngle - startAngle;
if (deltaAngle > 180) {
endAngle -= 360; // Rotate counterclockwise
} else if (deltaAngle < -180) {
endAngle += 360; // Rotate clockwise
}
timer = 0;
rotating = true;
this.actionAfter = actionAfter; // Store the action to execute after rotation
}
private float getEnemyAngle(Vector3f enemyPos){
// Direction to the enemy in the XY plane
Vector3f direction = enemyPos.subtract(spatial.getLocalTranslation());
direction.z = 0; // Project to XY plane
direction.normalizeLocal();
Vector3f reference = Vector3f.UNIT_Y.mult(-1);
// Calculate the angle between the direction vector and the reference vector
float angle = FastMath.acos(reference.dot(direction));
// Determine rotation direction using the cross product
Vector3f cross = reference.cross(direction);
if (cross.z < 0) {
angle = -angle;
}
return (float) Math.toDegrees(angle); // Return the absolute angle in degrees
}
private float getOwnAngle() {
// Tank's forward direction in the XY plane
Vector3f forward = spatial.getLocalRotation().mult(Vector3f.UNIT_Y);
forward.z = 0; // Project to XY plane
forward.normalizeLocal();
// Reference vector: Positive X-axis
Vector3f reference = Vector3f.UNIT_Y;
// Calculate the angle between the forward vector and the reference vector
float angle = FastMath.acos(reference.dot(forward));
// Determine rotation direction using the cross product
Vector3f cross = reference.cross(forward);
if (cross.z < 0) { // For Z-up, check the Z component of the cross product
angle = -angle;
}
return (float) Math.toDegrees(angle); // Return the absolute angle in radians
}
}

View File

@@ -52,6 +52,7 @@ public GameView(MdgaApp app) {
@Override
public void onEnter() {
setOwnColor(Color.AIRFORCE);
camera.init(ownColor);
boardHandler.init();
guiHandler.init(ownColor);

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -1,4 +1,6 @@
world 0,0 90
treesBigBackground 0,0 90
treesSmallBackground 0,0 90
#Marine Pos
@@ -56,7 +58,8 @@ big_tent -10,-9 130
big_tent 9,-10 225
radar 0,10 -20
tank -1,-10 135
tank 0,-18 180
#tank 0,-18 180
tank_shoot 0,-18 180
tank 3,-18 180
tank -3,-18 180
@@ -270,3 +273,4 @@ treeBig 12,22 360

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,554 @@
# Blender 3.6.5
# www.blender.org
o tank_top
v 0.136104 -4.382030 2.447842
v 0.136104 -4.313100 2.681757
v -0.107755 -4.382030 2.447842
v -0.107755 -4.313100 2.681757
v 0.136104 -5.171963 2.680617
v 0.136104 -5.103033 2.914532
v -0.107755 -5.171963 2.680617
v -0.107755 -5.103033 2.914532
v 0.104217 -1.266581 1.563035
v 0.104217 -1.215678 1.735777
v -0.075869 -1.266581 1.563035
v -0.075869 -1.215678 1.735777
v 0.104218 -5.321341 2.757877
v 0.104218 -5.270438 2.930620
v -0.075868 -5.321341 2.757877
v -0.075868 -5.270438 2.930620
v 0.170290 -1.697908 1.621255
v 0.170290 -1.609653 1.920754
v -0.141942 -1.697908 1.621255
v -0.141942 -1.609653 1.920754
v 0.229706 -1.077489 1.376490
v 0.229706 -0.955645 1.789975
v -0.201358 -1.077489 1.376490
v -0.201358 -0.955645 1.789975
v 0.514900 0.276165 1.806222
v 0.514900 0.588869 2.433130
v -0.442998 0.276164 1.806222
v -0.442998 0.588869 2.433130
v 0.514900 0.342851 1.772958
v 0.514900 0.655556 2.399867
v -0.442998 0.342851 1.772958
v -0.442998 0.655556 2.399867
v -0.571633 -0.809063 1.704162
v -0.571633 -0.809063 2.393599
v -0.723737 -0.809063 1.704162
v -0.723737 -0.809063 2.393599
v -0.571633 -0.656959 1.704161
v -0.571633 -0.656959 2.393600
v -0.723737 -0.656959 1.704161
v -0.723737 -0.656959 2.393600
v -0.950927 -0.897974 2.389141
v -0.950927 -0.803313 2.389141
v -0.861627 -0.897974 2.604730
v -0.861627 -0.803313 2.604730
v -0.646038 -0.897974 2.694029
v -0.646038 -0.803313 2.694029
v -0.430449 -0.897974 2.604729
v -0.430449 -0.803313 2.604730
v -0.341149 -0.897974 2.389141
v -0.341149 -0.803313 2.389141
v -0.430449 -0.897974 2.173552
v -0.430449 -0.803313 2.173552
v -0.646038 -0.897974 2.084251
v -0.646038 -0.803313 2.084251
v -0.861627 -0.897974 2.173552
v -0.861627 -0.803313 2.173552
v -0.799948 -0.357073 2.051851
v -0.784767 0.368207 2.051851
v -0.423762 0.888095 2.051851
v 0.525389 0.907164 2.051851
v 0.864924 0.401350 2.051851
v 0.849742 -0.323930 2.051851
v 0.387428 -1.063397 2.051851
v -0.368214 -1.078578 2.051851
v -1.026731 -0.445682 1.384443
v -1.007409 0.477460 1.384443
v -0.547920 1.139177 1.384443
v 0.660166 1.163448 1.384443
v 1.092329 0.519645 1.384443
v 1.073006 -0.403497 1.384443
v 0.484569 -1.344695 1.384443
v -0.477218 -1.364018 1.384443
v -1.077985 -0.465708 1.887314
v -1.057726 0.502151 1.887314
v -0.575980 1.195922 1.887314
v 0.690626 1.221368 1.887314
v 1.143722 0.546380 1.887314
v 1.123464 -0.421479 1.887314
v 0.506523 -1.408269 1.887314
v -0.501853 -1.428528 1.887314
v -1.085964 0.516008 1.535923
v -0.591726 1.227766 1.535923
v 0.707720 1.253873 1.535923
v 1.172564 0.561383 1.535923
v 1.151780 -0.431571 1.535923
v 0.518844 -1.443946 1.535923
v -0.515678 -1.464730 1.535923
v -1.106748 -0.476946 1.535923
v 0.612842 -0.142856 2.090828
v 0.612842 0.599197 2.091472
v -0.540940 -0.142856 2.090828
v -0.540940 0.599197 2.091472
v 0.612842 -0.142788 2.011893
v 0.612842 0.599266 2.012537
v -0.540940 -0.142788 2.011893
v -0.540940 0.599265 2.012537
v 0.445467 -0.035209 2.095495
v 0.445467 0.491550 2.095952
v -0.373565 -0.035210 2.095495
v -0.373565 0.491550 2.095952
vn -0.0000 0.9592 -0.2827
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.9592 0.2827
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.2827 -0.9592
vn -0.0000 0.2827 0.9592
vn -0.9960 -0.0855 0.0252
vn 0.9960 -0.0855 0.0252
vn -0.0000 -0.3670 -0.9302
vn -0.0000 0.1961 0.9806
vn -0.0000 -0.8949 0.4464
vn -0.0000 0.8949 -0.4464
vn -0.0000 -0.4464 -0.8949
vn -0.0000 0.4464 0.8949
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.0000 -0.0000 1.0000
vn -0.9239 -0.0000 0.3827
vn -0.3827 -0.0000 0.9239
vn 0.3827 -0.0000 0.9239
vn 0.9239 -0.0000 0.3827
vn 0.9239 -0.0000 -0.3827
vn 0.3827 -0.0000 -0.9239
vn -0.3827 -0.0000 -0.9239
vn -0.9239 -0.0000 -0.3827
vn -0.5124 0.0107 0.8587
vn -0.3944 0.2739 0.8772
vn -0.0094 0.4678 0.8838
vn 0.3870 0.2598 0.8847
vn 0.5124 -0.0107 0.8587
vn 0.4253 -0.2659 0.8651
vn 0.0086 -0.4282 0.9037
vn -0.4187 -0.2505 0.8729
vn -0.8549 -0.5116 0.0863
vn 0.0200 -0.9946 0.1017
vn 0.8450 -0.5283 0.0833
vn 0.9965 -0.0209 0.0809
vn 0.8268 0.5550 0.0916
vn -0.0200 0.9956 0.0911
vn -0.8182 0.5681 0.0882
vn -0.9965 0.0209 0.0809
vn -0.8856 0.0185 -0.4640
vn -0.7133 0.4953 -0.4959
vn -0.0173 0.8609 -0.5085
vn 0.7140 0.4793 -0.5103
vn 0.8856 -0.0185 -0.4640
vn 0.7463 -0.4666 -0.4746
vn 0.0168 -0.8346 -0.5506
vn -0.7489 -0.4482 -0.4881
vn -0.0000 -0.0009 1.0000
vn -0.0000 0.0009 -1.0000
vn -0.0000 -1.0000 -0.0009
vn -0.0000 1.0000 0.0009
vt 0.302708 0.924112
vt 0.288040 0.909443
vt 0.302708 0.909443
vt 0.693823 0.755933
vt 0.708491 0.805468
vt 0.693821 0.805468
vt 0.933974 0.202686
vt 0.919330 0.188017
vt 0.933973 0.188017
vt 0.651344 0.857452
vt 0.636674 0.807918
vt 0.651343 0.807918
vt 0.134278 0.805715
vt 0.119609 0.855249
vt 0.119609 0.805715
vt 0.708491 0.751615
vt 0.693871 0.702081
vt 0.708540 0.702096
vt 0.766441 0.570082
vt 0.755608 0.559249
vt 0.766441 0.559249
vt 0.537931 0.359392
vt 0.548757 0.613657
vt 0.537924 0.613657
vt 0.781573 0.570082
vt 0.770759 0.559250
vt 0.781572 0.559250
vt 0.579073 0.613652
vt 0.568233 0.359392
vt 0.579066 0.359392
vt 0.563915 0.359392
vt 0.553082 0.613655
vt 0.553082 0.359392
vt 0.437696 0.622253
vt 0.448781 0.368077
vt 0.448529 0.622264
vt 0.615148 0.975854
vt 0.633896 0.957072
vt 0.633897 0.975854
vt 0.948652 0.917591
vt 0.926304 0.957587
vt 0.929870 0.917591
vt 0.106854 0.798464
vt 0.132782 0.772534
vt 0.132782 0.798464
vt 0.952676 0.496495
vt 0.930312 0.536496
vt 0.926746 0.496495
vt 0.938021 0.614748
vt 0.960377 0.574830
vt 0.956803 0.614748
vt 0.948620 0.913273
vt 0.926304 0.873209
vt 0.952234 0.873235
vt 0.288040 0.924112
vt 0.708492 0.755933
vt 0.919331 0.202686
vt 0.636675 0.857452
vt 0.134278 0.855249
vt 0.693822 0.751601
vt 0.755609 0.570082
vt 0.548764 0.359392
vt 0.770759 0.570082
vt 0.568241 0.613652
vt 0.563915 0.613655
vt 0.437949 0.368066
vt 0.615148 0.957072
vt 0.952234 0.957587
vt 0.106853 0.772534
vt 0.949094 0.536496
vt 0.934447 0.574830
vt 0.929838 0.913255
vt 0.040925 0.927951
vt 0.002159 0.870340
vt 0.040923 0.870330
vt 0.834247 0.352865
vt 0.838729 0.310724
vt 0.838729 0.352865
vt 0.508750 0.936735
vt 0.546231 0.879133
vt 0.546232 0.936754
vt 0.843047 0.310724
vt 0.847530 0.352865
vt 0.843047 0.352865
vt 0.697810 0.640142
vt 0.693822 0.697763
vt 0.693822 0.640142
vt 0.323097 0.582179
vt 0.319198 0.524554
vt 0.323154 0.524558
vt 0.768084 0.828693
vt 0.777234 0.870091
vt 0.768084 0.870092
vt 0.499788 0.814544
vt 0.508937 0.856016
vt 0.499788 0.856016
vt 0.218712 0.819723
vt 0.227862 0.861192
vt 0.218712 0.861192
vt 0.420031 0.812900
vt 0.429180 0.854372
vt 0.420031 0.854372
vt 0.785891 0.559250
vt 0.795040 0.568399
vt 0.785891 0.568399
vt 0.537924 0.700847
vt 0.547080 0.691706
vt 0.547071 0.700856
vt 0.966064 0.285237
vt 0.971814 0.298192
vt 0.966120 0.298192
vt 0.453257 0.607137
vt 0.458792 0.620111
vt 0.453099 0.620105
vt 0.453125 0.594168
vt 0.458949 0.607142
vt 0.961680 0.298192
vt 0.956052 0.285237
vt 0.961746 0.285237
vt 0.961746 0.311174
vt 0.955987 0.298192
vt 0.578003 0.963076
vt 0.583636 0.950107
vt 0.583697 0.963076
vt 0.713986 0.956996
vt 0.737947 0.947070
vt 0.747872 0.971032
vt 0.578003 0.937139
vt 0.577943 0.950107
vt 0.971758 0.311174
vt 0.966064 0.311174
vt 0.307851 0.954728
vt 0.317762 0.944793
vt 0.331777 0.978655
vt 0.921986 0.878344
vt 0.905406 0.827575
vt 0.921986 0.820132
vt 0.884350 0.795866
vt 0.893886 0.777817
vt 0.827291 0.793524
vt 0.817744 0.774692
vt 0.789645 0.814701
vt 0.806235 0.823505
vt 0.789645 0.872913
vt 0.833108 0.912166
vt 0.825506 0.933015
vt 0.878533 0.914030
vt 0.886125 0.935503
vt 0.036904 0.863435
vt 0.057955 0.805815
vt 0.058039 0.865604
vt 0.893784 0.134399
vt 0.914942 0.195798
vt 0.893712 0.196631
vt 0.011369 0.804651
vt 0.032412 0.863875
vt 0.011276 0.866012
vt 0.032503 0.745834
vt 0.011370 0.744910
vt 0.032435 0.705568
vt 0.011300 0.703600
vt 0.297104 0.788044
vt 0.318245 0.865182
vt 0.297086 0.866212
vt 0.057959 0.746102
vt 0.036897 0.705526
vt 0.058032 0.703600
vt 0.036826 0.746953
vt 0.067083 0.748470
vt 0.067078 0.803985
vt 0.067151 0.708957
vt 0.288040 0.863346
vt 0.288056 0.790674
vt 0.002181 0.709075
vt 0.002246 0.747480
vt 0.002245 0.803021
vt 0.002159 0.860067
vt 0.884977 0.194314
vt 0.885044 0.136458
vt 0.067157 0.859570
vt 0.709979 0.282916
vt 0.754532 0.352364
vt 0.709910 0.352320
vt 0.702128 0.640146
vt 0.706914 0.684776
vt 0.702166 0.684781
vt 0.415360 0.813107
vt 0.370725 0.882511
vt 0.370725 0.813107
vt 0.427272 0.808484
vt 0.432057 0.763854
vt 0.432020 0.808488
vt 0.542664 0.617975
vt 0.537927 0.687379
vt 0.537924 0.617975
vt 0.457848 0.589850
vt 0.453099 0.520446
vt 0.457847 0.520446
vt 0.919379 0.134399
vt 0.951006 0.183699
vt 0.919330 0.183667
vt 0.002161 0.927961
vt 0.834247 0.310724
vt 0.508749 0.879113
vt 0.847530 0.310724
vt 0.697810 0.697763
vt 0.319140 0.582175
vt 0.777234 0.828693
vt 0.508937 0.814544
vt 0.227862 0.819722
vt 0.429180 0.812900
vt 0.795040 0.559250
vt 0.537933 0.691697
vt 0.971758 0.285237
vt 0.458817 0.594174
vt 0.956052 0.311174
vt 0.723911 0.980958
vt 0.713986 0.971033
vt 0.723911 0.947070
vt 0.747872 0.956995
vt 0.737947 0.980958
vt 0.583697 0.937139
vt 0.331777 0.944776
vt 0.341688 0.954686
vt 0.341688 0.968720
vt 0.317762 0.978673
vt 0.307851 0.968762
vt 0.905406 0.871198
vt 0.806235 0.867128
vt 0.036821 0.805157
vt 0.915012 0.135139
vt 0.032502 0.804065
vt 0.318263 0.788989
vt 0.754601 0.282960
vt 0.706876 0.640142
vt 0.415360 0.882511
vt 0.427309 0.763850
vt 0.542666 0.687379
vt 0.453100 0.589850
vt 0.951055 0.134431
s 1
f 3/1/1 2/2/1 1/3/1
f 7/4/2 4/5/2 3/6/2
f 5/7/3 8/8/3 7/9/3
f 1/10/4 6/11/4 5/12/4
f 1/13/5 7/14/5 3/15/5
f 8/16/6 2/17/6 4/18/6
f 11/19/1 10/20/1 9/21/1
f 15/22/2 12/23/2 11/24/2
f 13/25/3 16/26/3 15/27/3
f 9/28/4 14/29/4 13/30/4
f 9/31/5 15/32/5 11/33/5
f 14/34/6 12/35/6 16/36/6
f 18/37/3 19/38/3 17/39/3
f 20/40/7 23/41/7 19/42/7
f 24/43/1 21/44/1 23/45/1
f 22/46/8 17/47/8 21/48/8
f 19/49/9 21/50/9 17/51/9
f 20/52/10 22/53/10 24/54/10
f 3/1/1 4/55/1 2/2/1
f 7/4/2 8/56/2 4/5/2
f 5/7/3 6/57/3 8/8/3
f 1/10/4 2/58/4 6/11/4
f 1/13/5 5/59/5 7/14/5
f 8/16/6 6/60/6 2/17/6
f 11/19/1 12/61/1 10/20/1
f 15/22/2 16/62/2 12/23/2
f 13/25/3 14/63/3 16/26/3
f 9/28/4 10/64/4 14/29/4
f 9/31/5 13/65/5 15/32/5
f 14/34/6 10/66/6 12/35/6
f 18/37/3 20/67/3 19/38/3
f 20/40/7 24/68/7 23/41/7
f 24/43/1 22/69/1 21/44/1
f 22/46/8 18/70/8 17/47/8
f 19/49/9 23/71/9 21/50/9
f 20/52/10 18/72/10 22/53/10
f 25/73/11 28/74/11 27/75/11
f 27/76/2 32/77/2 31/78/2
f 32/79/12 29/80/12 31/81/12
f 30/82/4 25/83/4 29/84/4
f 31/85/13 25/86/13 27/87/13
f 32/88/14 26/89/14 30/90/14
f 34/91/15 35/92/15 33/93/15
f 36/94/2 39/95/2 35/96/2
f 40/97/16 37/98/16 39/99/16
f 38/100/4 33/101/4 37/102/4
f 35/103/17 37/104/17 33/105/17
f 36/106/18 38/107/18 40/108/18
f 43/109/19 42/110/19 41/111/19
f 45/112/20 44/113/20 43/114/20
f 47/115/21 46/116/21 45/112/21
f 49/117/22 48/118/22 47/119/22
f 51/120/23 50/121/23 49/117/23
f 51/122/24 54/123/24 52/124/24
f 46/125/16 50/126/16 54/127/16
f 55/128/25 54/123/25 53/129/25
f 41/111/26 56/130/26 55/131/26
f 45/132/15 43/133/15 51/134/15
f 73/135/27 58/136/27 74/137/27
f 74/137/28 59/138/28 75/139/28
f 75/139/29 60/140/29 76/141/29
f 60/140/30 77/142/30 76/141/30
f 61/143/31 78/144/31 77/142/31
f 78/144/32 63/145/32 79/146/32
f 61/143/18 60/140/18 59/138/18
f 79/146/33 64/147/33 80/148/33
f 64/147/34 73/135/34 80/148/34
f 80/149/35 88/150/35 87/151/35
f 86/152/36 80/153/36 87/154/36
f 85/155/37 79/156/37 86/157/37
f 77/158/38 85/155/38 84/159/38
f 76/160/39 84/159/39 83/161/39
f 82/162/40 76/163/40 83/164/40
f 81/165/41 75/166/41 82/167/41
f 88/150/42 74/168/42 81/165/42
f 88/150/43 66/169/43 65/170/43
f 81/165/44 67/171/44 66/169/44
f 82/162/45 68/172/45 67/173/45
f 68/174/46 84/159/46 69/175/46
f 69/175/47 85/155/47 70/176/47
f 85/155/48 71/177/48 70/176/48
f 86/152/49 72/178/49 71/179/49
f 72/180/50 88/150/50 65/170/50
f 89/181/51 92/182/51 91/183/51
f 92/184/2 95/185/2 91/186/2
f 96/187/52 93/188/52 95/189/52
f 93/190/4 90/191/4 89/192/4
f 95/193/53 89/194/53 91/195/53
f 96/196/54 90/197/54 94/198/54
f 97/199/51 100/200/51 99/201/51
f 25/73/11 26/202/11 28/74/11
f 27/76/2 28/203/2 32/77/2
f 32/79/12 30/204/12 29/80/12
f 30/82/4 26/205/4 25/83/4
f 31/85/13 29/206/13 25/86/13
f 32/88/14 28/207/14 26/89/14
f 34/91/15 36/208/15 35/92/15
f 36/94/2 40/209/2 39/95/2
f 40/97/16 38/210/16 37/98/16
f 38/100/4 34/211/4 33/101/4
f 35/103/17 39/212/17 37/104/17
f 36/106/18 34/213/18 38/107/18
f 43/109/19 44/214/19 42/110/19
f 45/112/20 46/116/20 44/113/20
f 47/115/21 48/215/21 46/116/21
f 49/117/22 50/121/22 48/118/22
f 51/120/23 52/216/23 50/121/23
f 51/122/24 53/129/24 54/123/24
f 42/217/16 44/218/16 46/125/16
f 46/125/16 48/219/16 50/126/16
f 50/126/16 52/220/16 54/127/16
f 54/127/16 56/221/16 42/217/16
f 42/217/16 46/125/16 54/127/16
f 55/128/25 56/222/25 54/123/25
f 41/111/26 42/110/26 56/130/26
f 43/133/15 41/223/15 51/134/15
f 41/223/15 55/224/15 51/134/15
f 55/224/15 53/225/15 51/134/15
f 51/134/15 49/226/15 47/227/15
f 47/227/15 45/132/15 51/134/15
f 73/135/27 57/228/27 58/136/27
f 74/137/28 58/136/28 59/138/28
f 75/139/29 59/138/29 60/140/29
f 60/140/30 61/143/30 77/142/30
f 61/143/31 62/229/31 78/144/31
f 78/144/32 62/229/32 63/145/32
f 59/138/18 58/136/18 61/143/18
f 58/136/18 57/228/18 62/229/18
f 61/143/18 58/136/18 62/229/18
f 57/228/18 64/147/18 63/145/18
f 63/145/18 62/229/18 57/228/18
f 79/146/33 63/145/33 64/147/33
f 64/147/34 57/228/34 73/135/34
f 80/149/35 73/230/35 88/150/35
f 86/152/36 79/231/36 80/153/36
f 85/155/37 78/232/37 79/156/37
f 77/158/38 78/232/38 85/155/38
f 76/160/39 77/158/39 84/159/39
f 82/162/40 75/233/40 76/163/40
f 81/165/41 74/168/41 75/166/41
f 88/150/42 73/230/42 74/168/42
f 88/150/43 81/165/43 66/169/43
f 81/165/44 82/167/44 67/171/44
f 82/162/45 83/164/45 68/172/45
f 68/174/46 83/161/46 84/159/46
f 69/175/47 84/159/47 85/155/47
f 85/155/48 86/157/48 71/177/48
f 86/152/49 87/154/49 72/178/49
f 72/180/50 87/151/50 88/150/50
f 89/181/51 90/234/51 92/182/51
f 92/184/2 96/235/2 95/185/2
f 96/187/52 94/236/52 93/188/52
f 93/190/4 94/237/4 90/191/4
f 95/193/53 93/238/53 89/194/53
f 96/196/54 92/239/54 90/197/54
f 97/199/51 98/240/51 100/200/51

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 MiB

After

Width:  |  Height:  |  Size: 13 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 MiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
package pp.mdga.notification;
import pp.mdga.game.Color;
import java.util.UUID;
/**
@@ -10,12 +12,14 @@ public class ThrowPieceNotification extends Notification {
* The id of the piece that was thrown.
*/
private final UUID pieceId;
private final Color throwColor;
/**
* This constructor is used to create a new ThrowPieceNotification
*/
public ThrowPieceNotification(UUID pieceId) {
public ThrowPieceNotification(UUID pieceId, Color throwColor) {
this.pieceId = pieceId;
this.throwColor = throwColor;
}
/**
@@ -26,4 +30,8 @@ public ThrowPieceNotification(UUID pieceId) {
public UUID getPieceId() {
return pieceId;
}
public Color getThrowColor() {
return throwColor;
}
}