edited 'SeaSynchronizer' and 'ShipControl' for Nr. 12
so now the fire on the ship will be displayed, the seasynchronizer handels it, in the 'ShipControl' the sinking of a sunken ship is implemented
This commit is contained in:
@@ -29,6 +29,11 @@
|
||||
import pp.battleship.model.ShipMap;
|
||||
import pp.battleship.model.Shot;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.lang.System.Logger.Level;
|
||||
import java.util.Timer;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static pp.util.FloatMath.HALF_PI;
|
||||
import static pp.util.FloatMath.PI;
|
||||
@@ -110,15 +115,54 @@ private Spatial handleHit(Shot shot) {
|
||||
final ParticleEmitter particleEmitter = createHitParticle(shot);
|
||||
particleEmitter.getLocalTranslation().subtractLocal(shipNode.getLocalTranslation());
|
||||
shipNode.attachChild(particleEmitter);
|
||||
if (ship.isDestroyed()) {
|
||||
for (int i = 0; i < 50; i++) {
|
||||
float r = (float) 0.001 * i;
|
||||
shipNode.move(0, -r, 0);
|
||||
}
|
||||
}
|
||||
final ParticleEmitter fire = createFire(shot);
|
||||
shipNode.attachChild(fire);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* this method attach fire to the ship, if it is hit
|
||||
* @param shot the shot, that hit the ship
|
||||
* @return the Fire
|
||||
*/
|
||||
|
||||
private ParticleEmitter createFire(Shot shot) {
|
||||
ParticleEmitter hitEffect = new ParticleEmitter("HitEffect", Type.Triangle, 5000);
|
||||
hitEffect.setMaterial(new Material(app.getAssetManager(), PARTICLE));
|
||||
hitEffect.setImagesX(2);
|
||||
hitEffect.setImagesY(2);
|
||||
hitEffect.setStartColor(ColorRGBA.Orange);
|
||||
hitEffect.setEndColor(ColorRGBA.Red);
|
||||
hitEffect.setStartSize(0.1f);
|
||||
hitEffect.setEndSize(0.1f);
|
||||
hitEffect.setParticlesPerSec(2);
|
||||
hitEffect.setLowLife(1f);
|
||||
hitEffect.setHighLife(1f);
|
||||
final Node shipNode = requireNonNull((Node) getSpatial(map.findShipAt(shot.getX(), shot.getY())), "Missing ship node");
|
||||
Vector3f shipNodePos = shipNode.getLocalTranslation();
|
||||
Vector3f shotWorld = mapToWorldCord(shot.getX(), shot.getY());
|
||||
Vector3f firePos = shotWorld.subtract(shipNodePos);
|
||||
if (map.findShipAt(shot.getX(), shot.getY()).getLength() == 2) {
|
||||
hitEffect.setLocalTranslation(firePos.x, 0.25f, firePos.z);
|
||||
}
|
||||
else {
|
||||
hitEffect.setLocalTranslation(firePos.x, 0.5f, firePos.z);
|
||||
}
|
||||
return hitEffect;
|
||||
}
|
||||
|
||||
/**
|
||||
* this method converts 2d to 3d positions
|
||||
*
|
||||
* @param x x-Coordinate
|
||||
* @param y-Coordinate
|
||||
* @return the Position as a 3d Vector
|
||||
*/
|
||||
|
||||
private Vector3f mapToWorldCord(int x, int y) {
|
||||
return new Vector3f(y + 0.5f, 0, x + 0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
* this method creates the particles, when the shot misses
|
||||
*
|
||||
@@ -175,28 +219,6 @@ private ParticleEmitter createHitParticle(Shot shot) {
|
||||
return hitEffect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a cylinder geometry representing the specified shot.
|
||||
* The appearance of the cylinder depends on whether the shot is a hit or a miss.
|
||||
*
|
||||
* @param shot the shot to be represented
|
||||
* @return the geometry representing the shot
|
||||
*/
|
||||
private Geometry createCylinder(Shot shot) {
|
||||
final ColorRGBA color = shot.isHit() ? HIT_COLOR : SPLASH_COLOR;
|
||||
final float height = shot.isHit() ? 1.2f : 0.1f;
|
||||
|
||||
final Cylinder cylinder = new Cylinder(2, 20, 0.45f, height, true);
|
||||
final Geometry geometry = new Geometry(SHOT, cylinder);
|
||||
|
||||
geometry.setMaterial(createColoredMaterial(color));
|
||||
geometry.rotate(HALF_PI, 0f, 0f);
|
||||
// compute the center of the shot in world coordinates
|
||||
geometry.setLocalTranslation(shot.getY() + 0.5f, 0f, shot.getX() + 0.5f);
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a {@link Battleship} and creates a graphical representation of it.
|
||||
* The representation is either a 3D model or a simple box depending on the
|
||||
@@ -213,7 +235,7 @@ public Spatial visit(Battleship ship) {
|
||||
final float x = 0.5f * (ship.getMinY() + ship.getMaxY() + 1f);
|
||||
final float z = 0.5f * (ship.getMinX() + ship.getMaxX() + 1f);
|
||||
node.setLocalTranslation(x, 0f, z);
|
||||
node.addControl(new ShipControl(ship));
|
||||
node.addControl(new ShipControl(ship, map));
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -271,6 +293,7 @@ private Spatial createSubmarine(Battleship ship) {
|
||||
final Spatial model = app.getAssetManager().loadModel(SUBMARINE);
|
||||
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()), 0f);
|
||||
model.scale(0.25f);
|
||||
model.move(0, -0.2f, 0);
|
||||
|
||||
model.setShadowMode(ShadowMode.CastAndReceive);
|
||||
|
||||
|
||||
@@ -11,9 +11,13 @@
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.ViewPort;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.control.AbstractControl;
|
||||
import pp.battleship.model.Battleship;
|
||||
import pp.battleship.model.ShipMap;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static pp.util.FloatMath.DEG_TO_RAD;
|
||||
import static pp.util.FloatMath.TWO_PI;
|
||||
import static pp.util.FloatMath.sin;
|
||||
@@ -48,6 +52,18 @@ class ShipControl extends AbstractControl {
|
||||
*/
|
||||
private float time;
|
||||
|
||||
/**
|
||||
* this attribute is the ship, this ShipControl controls
|
||||
*/
|
||||
|
||||
private final Battleship ship;
|
||||
|
||||
/**
|
||||
* this CONST represents the sinking height, when the ship will be removed
|
||||
*/
|
||||
|
||||
private static final Float SINKING_HEIGHT = -0.6f;
|
||||
|
||||
/**
|
||||
* Constructs a new ShipControl instance for the specified Battleship.
|
||||
* The ship's orientation determines the axis of rotation, while its length influences
|
||||
@@ -55,7 +71,7 @@ class ShipControl extends AbstractControl {
|
||||
*
|
||||
* @param ship the Battleship object to control
|
||||
*/
|
||||
public ShipControl(Battleship ship) {
|
||||
public ShipControl(Battleship ship, ShipMap map) {
|
||||
// Determine the axis of rotation based on the ship's orientation
|
||||
axis = switch (ship.getRot()) {
|
||||
case LEFT, RIGHT -> Vector3f.UNIT_X;
|
||||
@@ -65,6 +81,7 @@ public ShipControl(Battleship ship) {
|
||||
// Set the cycle duration and amplitude based on the ship's length
|
||||
cycle = ship.getLength() * 2f;
|
||||
amplitude = 5f * DEG_TO_RAD / ship.getLength();
|
||||
this.ship = ship;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,6 +94,12 @@ public ShipControl(Battleship ship) {
|
||||
protected void controlUpdate(float tpf) {
|
||||
// If spatial is null, do nothing
|
||||
if (spatial == null) return;
|
||||
if (ship.isDestroyed() && spatial.getLocalTranslation().getY() < SINKING_HEIGHT) { // removes the ship, if it is completely sunk
|
||||
spatial.getParent().detachChild(spatial);
|
||||
}
|
||||
else if (ship.isDestroyed() && spatial.getLocalTranslation().getY() >= SINKING_HEIGHT) { // sink the ship, if it's not completely sunk
|
||||
spatial.move(0, tpf * 0.1f * -1, 0);
|
||||
}
|
||||
|
||||
// Update the time within the oscillation cycle
|
||||
time = (time + tpf) % cycle;
|
||||
|
||||
Reference in New Issue
Block a user