diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/FadeControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/FadeControl.java new file mode 100644 index 00000000..c2a3c5ac --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/FadeControl.java @@ -0,0 +1,84 @@ +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; + +public class FadeControl extends InitControl { + private float duration; // Duration of the fade effect + private float timeElapsed = 0; + private boolean init = false; + private float startAlpha; + private float endAlpha; + private Runnable actionAfter; + + public FadeControl(float duration, float startAlpha, float endAlpha, Runnable actionAfter) { + this.duration = duration; + this.startAlpha = startAlpha; + this.endAlpha = endAlpha; + this.actionAfter = actionAfter; + } + + public FadeControl(float duration, float startAlpha, float endAlpha) { + this.duration = duration; + this.startAlpha = startAlpha; + this.endAlpha = endAlpha; + this.actionAfter = 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); + if(actionAfter != null) actionAfter.run(); + } + + 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"); + } + + /** + * 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. + */ + private float linInt(float start, float end, float t) { + return start + t * (end - start); + } +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MatrixAnimation.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MatrixAnimation.java index c0110319..ecc2d9a1 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MatrixAnimation.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MatrixAnimation.java @@ -10,20 +10,125 @@ import pp.mdga.client.MdgaApp; import pp.mdga.client.acoustic.MdgaSound; -import java.util.Random; -import java.util.Vector; +import java.util.*; public class MatrixAnimation extends InitControl { private MdgaApp app; private static final Random RANDOM = new Random(); + private Vector3f radarPos; + private Runnable runnable; + private boolean init = false; + private List activeEmitter = new ArrayList<>(); + private ParticleEmitter radarEmitter = null; + private float timeElapsed = 0f; - public MatrixAnimation(MdgaApp app){ + private enum MatrixState{ + RADAR_ON, + RADAR_OFF, + MATRIX_ON, + MATRIX_OFF + } + + private MatrixState state; + public MatrixAnimation(MdgaApp app, float duration, Vector3f radarPos, Runnable runnable){ this.app = app; + this.radarPos = radarPos; + this.runnable = runnable; } @Override protected void initSpatial() { + state = MatrixState.RADAR_ON; + System.out.println("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; + runnable.run(); + spatial.removeControl(this); + } + } + } + } + + 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(), @@ -35,9 +140,6 @@ protected void initSpatial() { } } - @Override - protected void controlUpdate(float tpf) { - } private void particleStream(ColorRGBA start, ColorRGBA end, float speedVar, Vector3f pos, float spawnVar){ Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Particle.j3md"); @@ -50,16 +152,17 @@ private void particleStream(ColorRGBA start, ColorRGBA end, float speedVar, Vect matrix.setSelectRandomImage(true); matrix.setStartColor(start); matrix.setEndColor(end); - matrix.getParticleInfluencer().setInitialVelocity(new Vector3f(0f, 0f, -4f - speedVar)); + 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, 0f); + matrix.setGravity(0, 0, 2f); matrix.setLowLife(3f); matrix.setHighLife(3f); - matrix.setLocalTranslation(pos.add(new Vector3f(0,0,15))); + 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() { diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java index 0cbbdff3..68414d00 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java @@ -1,6 +1,7 @@ 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; @@ -12,6 +13,7 @@ import pp.mdga.client.Asset; import pp.mdga.client.MdgaApp; import pp.mdga.client.acoustic.MdgaSound; +import pp.mdga.client.animation.FadeControl; import pp.mdga.client.animation.MatrixAnimation; import pp.mdga.client.animation.MoveControl; import pp.mdga.client.animation.JetAnimation; @@ -58,6 +60,8 @@ public class BoardHandler { private PieceControl selectedOwnPiece; private PieceControl selectedEnemyPiece; private DiceControl diceControl; + //Radar Position for Matrix animation + private Vector3f radarPos; /** * Creates a new BoardHandler. @@ -150,12 +154,18 @@ 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); default -> displayAsset(assetOnMap); } } } + private void addRadar(AssetOnMap assetOnMap) { + radarPos = gridToWorld(assetOnMap.x(), assetOnMap.y()); + displayAsset(assetOnMap); + } + /** * Converts an asset to its corresponding color. * @@ -189,14 +199,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.setColor("Diffuse", new ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f)); // Example: set 50% transparency (alpha = 0.5) - mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); // Enable alpha blending -// mat.getAdditionalRenderState().setDepthWrite(false); + 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; } @@ -728,7 +740,8 @@ 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)) ); } @@ -755,7 +768,17 @@ private void throwBomb(UUID uuid) { } private void throwMatrix(UUID uuid) { - pieces.get(uuid).getSpatial().addControl(new MatrixAnimation(app)); + Spatial piece = pieces.get(uuid).getSpatial(); + piece.addControl(new MatrixAnimation(app, 1, radarPos,()->{ + piece.addControl(new FadeControl(1,1,0, + () -> { + throwPiece(uuid); + piece.addControl(new FadeControl(1,0,1)); + } + )); + })); + + } private void throwMissle(UUID uuid) { diff --git a/Projekte/mdga/client/src/main/resources/Images/particle/radar_beam.png b/Projekte/mdga/client/src/main/resources/Images/particle/radar_beam.png new file mode 100644 index 00000000..6d2f317e Binary files /dev/null and b/Projekte/mdga/client/src/main/resources/Images/particle/radar_beam.png differ