Add jetAnimation

This commit is contained in:
Felix Koppe
2024-12-05 16:21:13 +01:00
parent 0e6a2499b7
commit 4a7c23708c
11 changed files with 345 additions and 13 deletions

View File

@@ -94,9 +94,7 @@ private void setupInput() {
inputManager.addListener(actionListener, "Settings", "Forward", "RotateRightMouse", "Click", "Left", "Right", "Test");
inputManager.addListener(analogListener, "MouseLeft", "MouseRight", "MouseScrollUp", "MouseScrollDown");
}
private boolean test = false;
UUID p = null;
/**
* Handles action-based input events such as key presses and mouse clicks.
*/
@@ -151,8 +149,19 @@ else if(boardSelect != null) {
if (name.equals("Right")) {
isRotateRight = !isRotateRight;
}
if(name.equals("Test") &&isPressed){
if(name.equals("Testx") &&isPressed){
if(app.getView() instanceof GameView gameView){
if(p == null) {
p = UUID.randomUUID();
gameView.getBoardHandler().addPlayer(Color.AIRFORCE,List.of(p,UUID.randomUUID(),UUID.randomUUID(),UUID.randomUUID()));
gameView.getBoardHandler().movePieceStartAnim(p,0);
gameView.getBoardHandler().movePieceAnim(p,0, 8);
} else {
gameView.getBoardHandler().throwBombAnim(p);
//gameView.getBoardHandler().movePieceStartAnim(p,0);
}
// gameView.getGuiHandler().rollRankingResult(Color.AIRFORCE, 1);
// gameView.getGuiHandler().rollRankingResult(Color.ARMY, 2);
// gameView.getGuiHandler().rollRankingResult(Color.NAVY, 3);
@@ -162,9 +171,9 @@ else if(boardSelect != null) {
// gameView.getBoardHandler().addPlayer(Color.AIRFORCE,List.of(p1,UUID.randomUUID(),UUID.randomUUID(),UUID.randomUUID()));
// gameView.getBoardHandler().movePieceStartAnim(p1,0);
gameView.getGuiHandler().drawCard(Color.ARMY);
gameView.getGuiHandler().addCardOwn(BonusCard.SHIELD);
gameView.getGuiHandler().playCardOwn(BonusCard.SHIELD);
//gameView.getGuiHandler().drawCard(Color.ARMY);
//gameView.getGuiHandler().addCardOwn(BonusCard.SHIELD);
//gameView.getGuiHandler().playCardOwn(BonusCard.SHIELD);

View File

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

View File

@@ -109,6 +109,13 @@ public void playSound(MdgaSound sound) {
case LEAVE:
assets.add(new SoundAssetDelayVolume(SoundAsset.UI_SOUND2, 0.6f, 0.0f));
break;
case JET:
assets.add(new SoundAssetDelayVolume(SoundAsset.JET, 1.0f, 0.0f));
break;
case EXPLOSION:
assets.add(new SoundAssetDelayVolume(SoundAsset.EXP, 1.0f, 4f));
assets.add(new SoundAssetDelayVolume(SoundAsset.THUNDER, 1.0f, 4f));
break;
default:
break;
}

View File

@@ -31,4 +31,6 @@ public enum MdgaSound {
OTHER_CONNECTED,
NOT_READY,
LEAVE,
JET,
EXPLOSION,
}

View File

@@ -28,6 +28,9 @@ enum SoundAsset {
POWERUP("powerup.wav"),
ROBOT_READY("robotReady.wav"),
UNIT_READY("unitReady.wav"),
JET("jet-overhead.wav"),
EXP("exp.ogg"),
THUNDER("thunder.ogg"),
CONNECTED("connected.wav");
private final String path;

View File

@@ -0,0 +1,126 @@
package pp.mdga.client.animation;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh.Type;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.control.AbstractControl;
import pp.mdga.client.MdgaApp;
public class Explosion {
private final Node rootNode;
private final MdgaApp app;
private final Vector3f location;
private ParticleEmitter fire;
private ParticleEmitter smoke;
private boolean triggered = false;
private final Material mat;
/**
* Konstruktor für die Explosion.
*
* @param app Die Hauptanwendung.
* @param rootNode Der Root-Knoten, an den die Explosion angefügt wird.
* @param location Der Ort der Explosion in World-Koordinaten.
*/
public Explosion(MdgaApp app, Node rootNode, Vector3f location) {
this.app = app;
this.rootNode = rootNode;
this.location = location;
this.mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Particle.j3md");
mat.getAdditionalRenderState().setDepthWrite(false);
mat.getAdditionalRenderState().setDepthTest(false);
}
/**
* Initialisiert den Partikel-Emitter für die Explosion.
*/
private void initializeEmitter() {
fire = new ParticleEmitter("Effect", Type.Triangle,50);
fire.setMaterial(mat);
fire.setStartColor(ColorRGBA.Yellow);
fire.setEndColor(ColorRGBA.Red);
fire.getParticleInfluencer().setInitialVelocity(new Vector3f(0.2f,0.2f,4f));
fire.getParticleInfluencer().setVelocityVariation(0.4f);
fire.setStartSize(0.1f);
fire.setEndSize(0.8f);
fire.setGravity(0, 0, -0.1f);
fire.setLowLife(0.5f);
fire.setHighLife(2.2f);
fire.setParticlesPerSec(0);
fire.setLocalTranslation(location);
fire.move(0, 0, 45);
smoke = new ParticleEmitter("Effect2", Type.Triangle,40);
smoke.setMaterial(mat);
smoke.setImagesX(2);
smoke.setImagesY(2);
smoke.setStartColor(ColorRGBA.DarkGray);
smoke.setEndColor(new ColorRGBA(0.05f, 0.05f, 0.05f, 1));
smoke.getParticleInfluencer().setInitialVelocity(new Vector3f(0.0f,0.0f,0.7f));
smoke.getParticleInfluencer().setVelocityVariation(0.5f);
smoke.setStartSize(0.2f);
smoke.setEndSize(0.5f);
smoke.setGravity(0, 0, -0.3f);
smoke.setLowLife(1.2f);
smoke.setHighLife(5.5f);
smoke.setParticlesPerSec(0);
smoke.setLocalTranslation(location);
smoke.move(0, 0, 45);
}
/**
* Löst die Explosion aus.
*/
public void trigger() {
if (!triggered) {
triggered = true;
initializeEmitter();
}
rootNode.attachChild(fire);
fire.emitAllParticles();
fire.addControl(new AbstractControl() {
private float elapsedTime = 0;
@Override
protected void controlUpdate(float tpf) {
elapsedTime += tpf;
if (elapsedTime > 10f) {
rootNode.detachChild(fire);
fire.removeControl(this);
}
}
@Override
protected void controlRender(com.jme3.renderer.RenderManager rm, com.jme3.renderer.ViewPort vp) {}
});
rootNode.attachChild(smoke);
smoke.emitAllParticles();
smoke.addControl(new AbstractControl() {
private float elapsedTime = 0;
@Override
protected void controlUpdate(float tpf) {
elapsedTime += tpf;
if (elapsedTime > 10f) {
rootNode.detachChild(smoke);
smoke.removeControl(this);
}
}
@Override
protected void controlRender(com.jme3.renderer.RenderManager rm, com.jme3.renderer.ViewPort vp) {}
});
}
}

View File

@@ -0,0 +1,175 @@
package pp.mdga.client.animation;
import com.jme3.material.Material;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import pp.mdga.client.Asset;
import pp.mdga.client.MdgaApp;
import pp.mdga.client.acoustic.MdgaSound;
import pp.mdga.client.board.BoardHandler;
import pp.mdga.client.view.GameView;
import java.util.UUID;
public class JetAnimation {
private final MdgaApp app; // Referenz auf die Hauptanwendung
private final Node rootNode; // Root-Knoten, an dem die Animation hängt
private Spatial jetModel; // Das Model des "jet"
private final Vector3f spawnPoint; // Spawnpunkt des Jets
private final Vector3f nodePoint; // Punkt des überflogenen Knotens
private final Vector3f despawnPoint; // Punkt, an dem der Jet despawnt
private final float curveHeight; // Maximale Höhe der Kurve
private final float animationDuration; // Dauer der Animation
private Explosion explosion;
private final UUID id;
/**
* Konstruktor für die ThrowAnimation-Klasse.
*
* @param app Die Hauptanwendung
* @param rootNode Der Root-Knoten, an dem der Jet angefügt wird
* @param uuid Die UUID des pieces
* @param targetPoint Der Punkt, an dem der Jet spawnt
* @param curveHeight Die maximale Höhe der Flugkurve
* @param animationDuration Die Gesamtdauer der Animation in Sekunden
*/
public JetAnimation(MdgaApp app, Node rootNode, UUID uuid, Vector3f targetPoint, float curveHeight, float animationDuration) {
Vector3f spawnPoint = targetPoint.add(170, 50, 50);
Vector3f controlPoint = targetPoint.add(new Vector3f(0, 0, -45));
Vector3f despawnPoint = targetPoint.add(-100, -100, 40);
this.app = app;
this.rootNode = rootNode;
this.spawnPoint = spawnPoint;
this.nodePoint = controlPoint;
this.despawnPoint = despawnPoint;
this.curveHeight = curveHeight;
this.animationDuration = animationDuration;
id = uuid;
explosion = new Explosion(app, rootNode, nodePoint);
}
/**
* Startet die Animation.
*/
public void start() {
app.getAcousticHandler().playSound(MdgaSound.JET);
spawnJet();
animateJet();
}
/**
* Spawnt den Jet an der spezifizierten Position.
*/
private void spawnJet() {
jetModel = app.getAssetManager().loadModel(Asset.jet.getModelPath());
jetModel.setLocalTranslation(spawnPoint);
jetModel.scale(Asset.jet.getSize());
jetModel.rotate(FastMath.HALF_PI, 0, 0);
jetModel.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
mat.setTexture("DiffuseMap", app.getAssetManager().loadTexture(Asset.jet.getDiffPath()));
jetModel.setMaterial(mat);
rootNode.attachChild(jetModel);
app.getAcousticHandler().playSound(MdgaSound.EXPLOSION);
}
/**
* Animiert den Jet entlang einer Kurve und lässt ihn anschließend verschwinden.
*/
private void animateJet() {
Vector3f controlPoint1 = spawnPoint.add(0, curveHeight, 0);
Vector3f controlPoint2 = nodePoint.add(0, curveHeight, 0);
BezierCurve3f curve = new BezierCurve3f(spawnPoint, controlPoint1, controlPoint2, despawnPoint);
app.getRootNode().addControl(new AbstractControl() {
private float elapsedTime = 0;
@Override
protected void controlUpdate(float tpf) {
elapsedTime += tpf;
float progress = elapsedTime / animationDuration;
if(elapsedTime > 4.2f) {
explosion.trigger();
}
if (progress > 1) {
rootNode.detachChild(jetModel);
this.spatial.removeControl(this);
} else {
Vector3f currentPos = curve.interpolate(progress);
Vector3f direction = curve.interpolateDerivative(progress).normalizeLocal();
jetModel.setLocalTranslation(currentPos);
jetModel.lookAt(currentPos.add(direction), Vector3f.UNIT_Z);
jetModel.rotate(-FastMath.HALF_PI, 0, (float) Math.toRadians(-25));
}
if (elapsedTime > 6.0f) {
GameView gameView = (GameView) app.getView();
BoardHandler boardHandler = gameView.getBoardHandler();
boardHandler.throwPieceAnim(id);
}
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
// Wird hier nicht benötigt
}
});
}
/**
* Repräsentiert eine 3D-Bezier-Kurve mit vier Kontrollpunkten.
*/
private static class BezierCurve3f {
private final Vector3f p0, p1, p2, p3;
public BezierCurve3f(Vector3f p0, Vector3f p1, Vector3f p2, Vector3f p3) {
this.p0 = p0;
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
}
public Vector3f interpolate(float t) {
float u = 1 - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
Vector3f point = p0.mult(uuu);
point = point.add(p1.mult(3 * uu * t));
point = point.add(p2.mult(3 * u * tt));
point = point.add(p3.mult(ttt));
return point;
}
public Vector3f interpolateDerivative(float t) {
float u = 1 - t;
float tt = t * t;
Vector3f derivative = p0.mult(-3 * u * u);
derivative = derivative.add(p1.mult(3 * u * u - 6 * u * t));
derivative = derivative.add(p2.mult(6 * u * t - 3 * tt));
derivative = derivative.add(p3.mult(3 * tt));
return derivative;
}
}
}

View File

@@ -10,9 +10,9 @@
import pp.mdga.client.Asset;
import pp.mdga.client.MdgaApp;
import pp.mdga.client.animation.MoveControl;
import pp.mdga.client.animation.JetAnimation;
import pp.mdga.client.gui.DiceControl;
import pp.mdga.game.Color;
import pp.mdga.game.Piece;
import java.util.*;
@@ -720,10 +720,20 @@ 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.
*
* @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();
}
/**

Binary file not shown.