Deathanimation working
This commit is contained in:
@ -14,10 +14,15 @@ import se.urmo.game.util.MyPoint;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
@Slf4j
|
||||
public class PacMan extends BaseAnimated {
|
||||
private enum PacmanState {
|
||||
ALIVE, DYING, DEAD
|
||||
}
|
||||
|
||||
public static final int PACMAN_SIZE = 32;
|
||||
public static final int PACMAN_OFFSET = PACMAN_SIZE / 2;
|
||||
private static final int COLLISION_BOX_SIZE = 16;
|
||||
@ -26,7 +31,7 @@ public class PacMan extends BaseAnimated {
|
||||
private static final int ANIMATION_UPDATE_FREQUENCY = 10;
|
||||
private static final double BASE_SPEED = 0.40;
|
||||
private boolean moving = false;
|
||||
private final BufferedImage[][] spriteSheets;
|
||||
private final BufferedImage[][] spriteSheets;// [row][col]
|
||||
private MyPoint position;
|
||||
private final CollisionChecker collisionChecker;
|
||||
private final LevelManager levelManager;
|
||||
@ -35,6 +40,16 @@ public class PacMan extends BaseAnimated {
|
||||
private Direction direction = Direction.NONE;
|
||||
private double pacmanLevelSpeed;
|
||||
|
||||
private static BufferedImage[] deathFramesBase; // original, flattened [0..7]
|
||||
private BufferedImage[] deathFrames; // working copy
|
||||
private long lastChangeNs;
|
||||
private static final long FRAME_NS = 80_000_000L; // 80 ms
|
||||
|
||||
// animation state
|
||||
@Setter
|
||||
private PacmanState state = PacmanState.ALIVE;
|
||||
private int deathFrameIdx = 0;
|
||||
|
||||
public PacMan(CollisionChecker collisionChecker, LevelManager levelManager) {
|
||||
super(ANIMATION_UPDATE_FREQUENCY, 4);
|
||||
this.collisionChecker = collisionChecker;
|
||||
@ -43,13 +58,19 @@ public class PacMan extends BaseAnimated {
|
||||
26 * GameMap.MAP_TILESIZE + GameMap.OFFSET_X,
|
||||
13 * GameMap.MAP_TILESIZE + GameMap.OFFSET_Y + ((double) GameMap.MAP_TILESIZE / 2));
|
||||
this.startPosition = this.position;
|
||||
this.spriteSheets = loadAnimation();
|
||||
Sprites spriteSheets1 = loadAnimation();
|
||||
this.spriteSheets = spriteSheets1.spriteSheets;
|
||||
this.deathFramesBase = spriteSheets1.deathFrames;
|
||||
this.pacmanLevelSpeed = this.levelManager.getPacmanLevelSpeed();
|
||||
}
|
||||
|
||||
private BufferedImage[][] loadAnimation() {
|
||||
record Sprites(BufferedImage[][] spriteSheets, BufferedImage[] deathFrames) {
|
||||
}
|
||||
|
||||
private Sprites loadAnimation() {
|
||||
BufferedImage[][] image = new BufferedImage[3][4];
|
||||
BufferedImage[][] spriteMap = new BufferedImage[6][4];
|
||||
BufferedImage[] deathFrames;
|
||||
|
||||
BufferedImage img = LoadSave.GetSpriteAtlas("sprites/PacManAssets-PacMan.png");
|
||||
for (int row = 0; row < 3; row++) {
|
||||
@ -59,7 +80,7 @@ public class PacMan extends BaseAnimated {
|
||||
}
|
||||
spriteMap[Direction.RIGHT.ordinal()] = image[0];
|
||||
spriteMap[Direction.LEFT.ordinal()] = Arrays.stream(image[0])
|
||||
.map(i -> LoadSave.rotate(i, 180))
|
||||
.map(i -> LoadSave.rotate(i, Direction.LEFT.angel))
|
||||
.toArray(BufferedImage[]::new);
|
||||
spriteMap[Direction.DOWN.ordinal()] = Arrays.stream(image[0])
|
||||
.map(i -> LoadSave.rotate(i, 90))
|
||||
@ -67,22 +88,64 @@ public class PacMan extends BaseAnimated {
|
||||
spriteMap[Direction.UP.ordinal()] = Arrays.stream(image[0])
|
||||
.map(i -> LoadSave.rotate(i, 270))
|
||||
.toArray(BufferedImage[]::new);
|
||||
spriteMap[4] = image[1];
|
||||
spriteMap[5] = image[2];
|
||||
return spriteMap;
|
||||
deathFrames = Stream.concat(Arrays.stream(image[1]), Arrays.stream(image[2]))
|
||||
.toArray(BufferedImage[]::new);
|
||||
|
||||
|
||||
return new Sprites(spriteMap, deathFrames);
|
||||
}
|
||||
|
||||
public void draw(Graphics g) {
|
||||
g.drawImage(
|
||||
spriteSheets[direction == Direction.NONE ? 0 : direction.ordinal()][aniIndex],
|
||||
(int) position.x - PACMAN_OFFSET,
|
||||
(int) position.y - PACMAN_OFFSET,
|
||||
PACMAN_SIZE,
|
||||
PACMAN_SIZE, null);
|
||||
switch (state) {
|
||||
case ALIVE -> drawAlive(g);
|
||||
case DYING -> drawDead(g);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawAlive(Graphics g) {
|
||||
if (state != PacmanState.ALIVE) return; // ignore if not dying/dead
|
||||
g.drawImage(
|
||||
spriteSheets[direction == Direction.NONE ? 0 : direction.ordinal()][aniIndex],
|
||||
(int) position.x - PACMAN_OFFSET,
|
||||
(int) position.y - PACMAN_OFFSET,
|
||||
PACMAN_SIZE,
|
||||
PACMAN_SIZE, null);
|
||||
}
|
||||
|
||||
private void drawDead(Graphics g) {
|
||||
if (state == PacmanState.ALIVE) return; // ignore if not dying/dead
|
||||
|
||||
g.drawImage(
|
||||
deathFrames[deathFrameIdx],
|
||||
(int) position.x - PACMAN_OFFSET,
|
||||
(int) position.y - PACMAN_OFFSET,
|
||||
PACMAN_SIZE,
|
||||
PACMAN_SIZE,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if(moving) {
|
||||
switch (state) {
|
||||
case ALIVE -> updateAlive();
|
||||
case DYING -> updateDead();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDead() {
|
||||
if (state != PacmanState.DYING) return;
|
||||
|
||||
long now = System.nanoTime();
|
||||
while (now - lastChangeNs >= FRAME_NS && deathFrameIdx < deathFramesBase.length - 1) {
|
||||
deathFrameIdx++;
|
||||
lastChangeNs += FRAME_NS; // carry over exact cadence
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAlive() {
|
||||
if (state != PacmanState.ALIVE) return;
|
||||
|
||||
if (moving) {
|
||||
MyPoint mpoint = switch (direction) {
|
||||
case RIGHT -> new MyPoint(position.x + getSpeed(), position.y);
|
||||
case LEFT -> new MyPoint(position.x - getSpeed(), position.y);
|
||||
@ -99,6 +162,21 @@ public class PacMan extends BaseAnimated {
|
||||
}
|
||||
}
|
||||
|
||||
// called by PlayingState when collision (non-frightened)
|
||||
public void startDeathAnimation() {
|
||||
log.info("Starting death animation");
|
||||
state = PacmanState.DYING;
|
||||
deathFrameIdx = 0;
|
||||
lastChangeNs = System.nanoTime(); // reset stopwatch right now
|
||||
deathFrames = Arrays.stream(deathFramesBase)
|
||||
.map(img -> LoadSave.rotate(img, direction.angel))
|
||||
.toArray(BufferedImage[]::new);
|
||||
}
|
||||
|
||||
public boolean isDeathDone() {
|
||||
return state == PacmanState.DEAD;
|
||||
}
|
||||
|
||||
private double getSpeed() {
|
||||
return BASE_SPEED * pacmanLevelSpeed;
|
||||
}
|
||||
@ -114,6 +192,8 @@ public class PacMan extends BaseAnimated {
|
||||
public void reset() {
|
||||
resetPosition();
|
||||
aniIndex = 0; // reset animation to start
|
||||
state = PacmanState.ALIVE;
|
||||
deathFrameIdx = 0;
|
||||
}
|
||||
|
||||
public Image getLifeIcon() {
|
||||
|
||||
Reference in New Issue
Block a user