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
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										47
									
								
								Projekte/mdga/client/src/main/java/pp/mdga/client/Util.java
									
									
									
									
									
										Normal 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,4 +38,7 @@ public enum MdgaSound {
 | 
			
		||||
    UI90,
 | 
			
		||||
    MISSILE,
 | 
			
		||||
    MATRIX,
 | 
			
		||||
    TURRET_ROTATE,
 | 
			
		||||
    TANK_SHOOT,
 | 
			
		||||
    TANK_EXPLOSION
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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.
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -52,6 +52,7 @@ public GameView(MdgaApp app) {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onEnter() {
 | 
			
		||||
        setOwnColor(Color.AIRFORCE);
 | 
			
		||||
        camera.init(ownColor);
 | 
			
		||||
        boardHandler.init();
 | 
			
		||||
        guiHandler.init(ownColor);
 | 
			
		||||
 
 | 
			
		||||
| 
		 After Width: | Height: | Size: 46 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Projekte/mdga/client/src/main/resources/Images/particle/line.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 140 B  | 
| 
		 After Width: | Height: | Size: 29 KiB  | 
| 
		 After Width: | Height: | Size: 18 KiB  | 
@@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Projekte/mdga/client/src/main/resources/Models/shell/shell.j3o
									
									
									
									
									
										Normal 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
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 10 MiB After Width: | Height: | Size: 13 MiB  | 
| 
		 After Width: | Height: | Size: 10 MiB  | 
							
								
								
									
										
											BIN
										
									
								
								Projekte/mdga/client/src/main/resources/Sounds/tank_shoot.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Projekte/mdga/client/src/main/resources/Sounds/turret_rotate.ogg
									
									
									
									
									
										Normal 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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||