Added Scatter-strategy
This commit is contained in:
@ -2,6 +2,7 @@ package se.urmo.game.collision;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import se.urmo.game.main.GamePanel;
|
||||
import se.urmo.game.util.Direction;
|
||||
import se.urmo.game.map.GameMap;
|
||||
|
||||
@ -44,7 +45,7 @@ public class CollisionChecker {
|
||||
|
||||
/**
|
||||
* Applies specific rules to movement
|
||||
* This for instance makes sure the tunnel left/right works.
|
||||
* This, for instance, makes sure the tunnel left/right works.
|
||||
*
|
||||
* @param dir
|
||||
* @param pos
|
||||
@ -55,7 +56,7 @@ public class CollisionChecker {
|
||||
public Point normalizePosition(Direction dir, Point pos, int agent_width, int agent_height) {
|
||||
int x = pos.x;
|
||||
int y = pos.y;
|
||||
int width = map.getWidth();
|
||||
int width = GamePanel.SCREEN_WIDTH;
|
||||
int height = map.getHeight();
|
||||
|
||||
// tunnel
|
||||
|
||||
@ -2,10 +2,12 @@ package se.urmo.game.collision;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import se.urmo.game.map.GameMap;
|
||||
import se.urmo.game.map.MapTile;
|
||||
import se.urmo.game.util.Direction;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Slf4j
|
||||
public class GhostCollisionChecker {
|
||||
@ -16,15 +18,38 @@ public class GhostCollisionChecker {
|
||||
}
|
||||
|
||||
public List<Direction> calculateDirectionAlternatives(Point position) {
|
||||
List<Direction> intersection = map.directionAlternatives(position);
|
||||
List<Direction> intersection = directionAlternatives(position);
|
||||
log.info("Possible travel directions: {}", intersection);
|
||||
return intersection;
|
||||
}
|
||||
|
||||
public List<Direction> directionAlternatives(Point position) {
|
||||
int row = (position.y - GameMap.OFFSET_Y) / GameMap.MAP_TILESIZE;
|
||||
int col = (position.x - GameMap.OFFSET_X) / GameMap.MAP_TILESIZE;
|
||||
|
||||
record DirectionCheck(int rowOffset, int colOffset, Direction direction) {}
|
||||
log.debug("At [{}][{}]", row, col);
|
||||
return Stream.of(
|
||||
new DirectionCheck(0, 1, Direction.RIGHT),
|
||||
new DirectionCheck(0, -1, Direction.LEFT),
|
||||
new DirectionCheck(1, 0, Direction.DOWN),
|
||||
new DirectionCheck(-1, 0, Direction.UP)
|
||||
)
|
||||
.filter(dc -> {
|
||||
int r = row + dc.rowOffset;
|
||||
int c = col + dc.colOffset;
|
||||
boolean solid = map.isSolid(r, c);
|
||||
log.debug("[{}][{}] {} is {}", r, c, dc.direction, solid ? "solid" : " not solid");
|
||||
return !solid;
|
||||
})
|
||||
.map(DirectionCheck::direction)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public Point canMoveTo(Direction dir, Point pos) {
|
||||
// -1 is because else we endup in next tile
|
||||
Point pp = new Point(pos.x + dir.dx * (GameMap.MAP_TILESIZE/2 - 1), pos.y + dir.dy * (GameMap.MAP_TILESIZE/2 -1) );
|
||||
|
||||
return ! map.isSolid(pp.x, pp.y) ? pos : null;
|
||||
return ! map.isSolid(pp) ? pos : null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
package se.urmo.game.entities;
|
||||
|
||||
import se.urmo.game.map.GameMap;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
public class BlinkyStrategy implements GhostStrategy {
|
||||
@Override
|
||||
public Point chooseTarget(PacMan pacman) {
|
||||
public Point chooseTarget(PacMan pacman, GameMap map) {
|
||||
return pacman.getTilePosition();
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,11 @@ import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Point;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
public class Ghost {
|
||||
@ -30,22 +34,25 @@ public class Ghost {
|
||||
private boolean moving = true;
|
||||
private int aniTick = 0;
|
||||
private int aniIndex = 0;
|
||||
private final GhostStrategy scaterStrategy;
|
||||
private GhostStrategy currentStrategy;
|
||||
private final BufferedImage[] animation;
|
||||
private int movementTick = 0;
|
||||
private Direction direction;
|
||||
private Direction prevDirection;
|
||||
private GhostMode mode;
|
||||
private GhostStrategy currentStrategy;
|
||||
|
||||
|
||||
public Ghost(GhostCollisionChecker collisionChecker, GhostStrategy strategy, BufferedImage[] animation) {
|
||||
public Ghost(GhostCollisionChecker collisionChecker, GhostStrategy strategy, GhostStrategy scaterStrategy, BufferedImage[] animation) {
|
||||
this.collisionChecker = collisionChecker;
|
||||
this.chaseStrategy = strategy;
|
||||
this.currentStrategy = strategy;
|
||||
this.scaterStrategy = scaterStrategy;
|
||||
this.animation = animation;
|
||||
position = new Point(
|
||||
13 * GameMap.MAP_TILESIZE + (GameMap.MAP_TILESIZE / 2) + GameMap.OFFSET_X,
|
||||
4 * GameMap.MAP_TILESIZE + (GameMap.MAP_TILESIZE / 2) + GameMap.OFFSET_Y);
|
||||
|
||||
this.currentStrategy = chaseStrategy;
|
||||
}
|
||||
|
||||
public void draw(Graphics g) {
|
||||
@ -62,20 +69,19 @@ public class Ghost {
|
||||
COLLISION_BOX_SIZE, null);
|
||||
}
|
||||
|
||||
public void update(PacMan pacman) {
|
||||
public void update(PacMan pacman, GameMap map) {
|
||||
updateAnimationTick();
|
||||
updatePosition(pacman);
|
||||
updatePosition(pacman, map);
|
||||
}
|
||||
|
||||
private void updatePosition(PacMan pacman) {
|
||||
private void updatePosition(PacMan pacman, GameMap map) {
|
||||
if (movementTick >= GHOST_MOVEMENT_UPDATE_FREQUENCY) {
|
||||
if (isAlligned(position)) {
|
||||
log.info("Evaluating possible directions");
|
||||
prevDirection = direction;
|
||||
direction = chooseDirection(
|
||||
collisionChecker.calculateDirectionAlternatives(position),
|
||||
currentStrategy.chooseTarget(pacman),
|
||||
prevDirection);
|
||||
prioritize(collisionChecker.calculateDirectionAlternatives(position)),
|
||||
currentStrategy.chooseTarget(pacman, map));
|
||||
log.info("selecting direction {}", direction);
|
||||
}
|
||||
|
||||
@ -93,17 +99,36 @@ public class Ghost {
|
||||
} else movementTick++;
|
||||
}
|
||||
|
||||
private Map<Direction, Integer> prioritize(List<Direction> directions) {
|
||||
return directions.stream()
|
||||
.filter(d -> d != Direction.NONE)
|
||||
.collect(Collectors.toMap(
|
||||
d -> d,
|
||||
d -> (prevDirection != null && d == prevDirection.opposite()) ? 2 : 1
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
private boolean isAlligned(Point pos) {
|
||||
int row = pos.x % GameMap.MAP_TILESIZE;
|
||||
int col = pos.y % GameMap.MAP_TILESIZE;
|
||||
return row == GameMap.MAP_TILESIZE / 2 && col == GameMap.MAP_TILESIZE / 2;
|
||||
}
|
||||
|
||||
private Direction chooseDirection(List<Direction> options, Point target, Direction prevDirection) {
|
||||
List<Direction> l = options.stream()
|
||||
// remove any option to go back
|
||||
.filter(d -> !(prevDirection != null && d.equals(prevDirection.opposite())))
|
||||
private Direction chooseDirection(Map<Direction, Integer> options, Point target) {
|
||||
|
||||
// Find the lowest priority
|
||||
int lowestPriority = options.values().stream()
|
||||
.mapToInt(Integer::intValue)
|
||||
.min()
|
||||
.orElse(Integer.MAX_VALUE);
|
||||
|
||||
// Return all directions that have this priority
|
||||
List<Direction> l = options.entrySet().stream()
|
||||
.filter(entry -> entry.getValue() == lowestPriority)
|
||||
.map(Map.Entry::getKey)
|
||||
.toList();
|
||||
|
||||
Direction best = l.getFirst();
|
||||
double bestDist = Double.MAX_VALUE;
|
||||
|
||||
@ -137,7 +162,7 @@ public class Ghost {
|
||||
this.mode = mode;
|
||||
switch (mode) {
|
||||
case CHASE -> currentStrategy = chaseStrategy;
|
||||
case SCATTER -> currentStrategy = null;
|
||||
case SCATTER -> currentStrategy = scaterStrategy;
|
||||
case FRIGHTENED -> currentStrategy = null;
|
||||
case EATEN -> currentStrategy = null;
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
package se.urmo.game.entities;
|
||||
|
||||
import se.urmo.game.map.GameMap;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
public interface GhostStrategy {
|
||||
Point chooseTarget(PacMan pacman);
|
||||
Point chooseTarget(PacMan pacman, GameMap map);
|
||||
}
|
||||
|
||||
@ -18,19 +18,20 @@ import java.util.Arrays;
|
||||
@Slf4j
|
||||
public class PacMan {
|
||||
public static final int PACMAN_SIZE = 32;
|
||||
public static final int PACMAN_OFFSET = PACMAN_SIZE / 2;
|
||||
private static final int COLLISION_BOX_SIZE = 16;
|
||||
private static final int COLLISION_BOX_OFFSET = (PACMAN_SIZE - COLLISION_BOX_SIZE) / 2;
|
||||
private final Game game;
|
||||
private int aniTick = 0;
|
||||
private int aniIndex = 0;
|
||||
private static final int ANIMATION_UPDATE_FREQUENCY = 25;
|
||||
private static final int ANIMATION_UPDATE_FREQUENCY = 10;
|
||||
private int speed = 1;
|
||||
@Setter
|
||||
private boolean moving;
|
||||
private final BufferedImage[][] movmentImages = new BufferedImage[4][4];
|
||||
private Point position;
|
||||
private static final BufferedImage COLLISION_BOX = MiscUtil.createOutlinedBox(COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, Color.yellow, 2);
|
||||
private CollisionChecker collisionChecker;
|
||||
private final CollisionChecker collisionChecker;
|
||||
@Setter
|
||||
@Getter
|
||||
private Direction direction = Direction.NONE;
|
||||
@ -65,17 +66,16 @@ public class PacMan {
|
||||
.toArray(BufferedImage[]::new);
|
||||
}
|
||||
|
||||
|
||||
public void draw(Graphics g) {
|
||||
g.drawImage(
|
||||
movmentImages[direction==Direction.NONE?0:direction.ordinal()][aniIndex],
|
||||
position.x - PACMAN_SIZE / 2,
|
||||
position.y - PACMAN_SIZE / 2,
|
||||
movmentImages[direction==Direction.NONE ? 0 : direction.ordinal()][aniIndex],
|
||||
position.x - PACMAN_OFFSET,
|
||||
position.y - PACMAN_OFFSET,
|
||||
PACMAN_SIZE,
|
||||
PACMAN_SIZE, null);
|
||||
g.drawImage(COLLISION_BOX, position.x - COLLISION_BOX_OFFSET, position.y - COLLISION_BOX_OFFSET, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, null);
|
||||
g.setColor(Color.BLUE);
|
||||
g.fillRect(position.x-1, position.y-1, 3, 3);
|
||||
//g.fillRect(position.x-1, position.y-1, 3, 3);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
@ -98,7 +98,6 @@ public class PacMan {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateAnimationTick() {
|
||||
if (moving) {
|
||||
aniTick++;
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
package se.urmo.game.entities;
|
||||
|
||||
import se.urmo.game.map.GameMap;
|
||||
import se.urmo.game.util.Direction;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
public class PinkyStrategy implements GhostStrategy{
|
||||
@Override
|
||||
public Point chooseTarget(PacMan pacman) {
|
||||
public Point chooseTarget(PacMan pacman, GameMap map) {
|
||||
Direction pacmanDir = pacman.getDirection();
|
||||
Point pacmanPos = pacman.getTilePosition();
|
||||
return switch (pacmanDir){
|
||||
case RIGHT -> new Point(pacmanPos.x + 4 * 16, pacmanPos.y);
|
||||
case LEFT -> new Point(pacmanPos.x - 4 * 16, pacmanPos.y);
|
||||
case DOWN -> new Point(pacmanPos.x, pacmanPos.y + 4 * 16);
|
||||
case UP -> new Point(pacmanPos.x, pacmanPos.y - 4 * 16);
|
||||
case RIGHT -> new Point(pacmanPos.x + 4 * GameMap.MAP_TILESIZE, pacmanPos.y);
|
||||
case LEFT -> new Point(pacmanPos.x - 4 * GameMap.MAP_TILESIZE, pacmanPos.y);
|
||||
case DOWN -> new Point(pacmanPos.x, pacmanPos.y + 4 * GameMap.MAP_TILESIZE);
|
||||
case UP -> new Point(pacmanPos.x, pacmanPos.y - 4 * GameMap.MAP_TILESIZE);
|
||||
case NONE -> pacmanPos;
|
||||
default -> throw new IllegalStateException("Illegal direction");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
12
src/main/java/se/urmo/game/entities/ScatterToTopRight.java
Normal file
12
src/main/java/se/urmo/game/entities/ScatterToTopRight.java
Normal file
@ -0,0 +1,12 @@
|
||||
package se.urmo.game.entities;
|
||||
|
||||
import se.urmo.game.map.GameMap;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
public class ScatterToTopRight implements GhostStrategy{
|
||||
@Override
|
||||
public Point chooseTarget(PacMan pacman, GameMap map) {
|
||||
return new Point((map.columns() -1) * GameMap.MAP_TILESIZE, 0);
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,6 @@ package se.urmo.game.map;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import se.urmo.game.main.GamePanel;
|
||||
import se.urmo.game.util.Direction;
|
||||
import se.urmo.game.util.LoadSave;
|
||||
|
||||
import java.awt.*;
|
||||
@ -12,7 +11,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Slf4j
|
||||
public class GameMap {
|
||||
@ -127,9 +125,7 @@ public class GameMap {
|
||||
public void draw(Graphics g) {
|
||||
for (int row = 0; row < mapData.length; row++) {
|
||||
for (int col = 0; col < mapData[row].length; col++) {
|
||||
MapTile tile = mapData[row][col];
|
||||
|
||||
BufferedImage tileImage = tile.getImage();
|
||||
BufferedImage tileImage = mapData[row][col].getImage();
|
||||
|
||||
if (tileImage != null) {
|
||||
int x = OFFSET_X + col * MAP_TILESIZE;
|
||||
@ -144,8 +140,8 @@ public class GameMap {
|
||||
return list.stream().allMatch(p -> isPassable(p.x, p.y));
|
||||
}
|
||||
public boolean isPassable(int x, int y) {
|
||||
int row = (y - OFFSET_Y) / MAP_TILESIZE;
|
||||
int col = (x - OFFSET_X) / MAP_TILESIZE;
|
||||
int row = getRow(y);
|
||||
int col = getCol(x);
|
||||
int tileY = (y - OFFSET_Y) % MAP_TILESIZE;
|
||||
int tileX = (x - OFFSET_X) % MAP_TILESIZE;
|
||||
log.trace("Point[x="+x+",y="+y+"] is row="+ row + ", col=" + col + " with reminder x=" +tileX+",y=" +tileY);
|
||||
@ -156,8 +152,12 @@ public class GameMap {
|
||||
return b;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return GamePanel.SCREEN_WIDTH;
|
||||
private static int getCol(int x) {
|
||||
return (x - OFFSET_X) / MAP_TILESIZE;
|
||||
}
|
||||
|
||||
private static int getRow(int y) {
|
||||
return (y - OFFSET_Y) / MAP_TILESIZE;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
@ -165,42 +165,36 @@ public class GameMap {
|
||||
}
|
||||
|
||||
public void removeTileImage(Point destination) {
|
||||
int row = (destination.y - OFFSET_Y) / MAP_TILESIZE;
|
||||
int col = (destination.x - OFFSET_X) / MAP_TILESIZE;
|
||||
int row = getRow(destination);
|
||||
int col = getCol(destination);
|
||||
MapTile tile = mapData[row][col];
|
||||
if(tile.getValue() == 0) tile.setImage(null);
|
||||
}
|
||||
|
||||
public List<Direction> directionAlternatives(Point position) {
|
||||
int row = (position.y - OFFSET_Y) / MAP_TILESIZE;
|
||||
int col = (position.x - OFFSET_X) / MAP_TILESIZE;
|
||||
|
||||
record DirectionCheck(int rowOffset, int colOffset, Direction direction) {}
|
||||
log.debug("At [{}][{}]", row, col);
|
||||
return Stream.of(
|
||||
new DirectionCheck(0, 1, Direction.RIGHT),
|
||||
new DirectionCheck(0, -1, Direction.LEFT),
|
||||
new DirectionCheck(1, 0, Direction.DOWN),
|
||||
new DirectionCheck(-1, 0, Direction.UP)
|
||||
)
|
||||
.filter(dc -> {
|
||||
int r = row + dc.rowOffset;
|
||||
int c = col + dc.colOffset;
|
||||
MapTile mapTile = mapData[r][c];
|
||||
boolean solid = mapTile.isSolid();
|
||||
log.debug("[{}][{}] {} is {} ({})", r, c, dc.direction, solid ? "solid" : " not solid", mapTile.getValue());
|
||||
return !solid;
|
||||
})
|
||||
.map(DirectionCheck::direction)
|
||||
.toList();
|
||||
private static int getCol(Point point) {
|
||||
return getCol(point.x);
|
||||
}
|
||||
|
||||
public boolean isSolid(int x, int y) {
|
||||
int row = (y - OFFSET_Y) / MAP_TILESIZE;
|
||||
int col = (x - OFFSET_X) / MAP_TILESIZE;
|
||||
private static int getRow(Point point) {
|
||||
return getRow(point.y);
|
||||
}
|
||||
|
||||
public boolean isSolid(Point pos) {
|
||||
int row = getRow(pos);
|
||||
int col = getCol(pos);
|
||||
return isSolid(row,col);
|
||||
}
|
||||
|
||||
|
||||
public boolean isSolid(int row, int col) {
|
||||
if (col >= columns() || col < 0 ) return true;
|
||||
MapTile mapTile = mapData[row][col];
|
||||
boolean solid = mapTile.isSolid();
|
||||
log.debug("[{}][{}] is {} ({})", row, col, solid ? "solid" : " not solid", mapTile.getValue());
|
||||
return solid;
|
||||
}
|
||||
|
||||
public int columns() {
|
||||
return (GamePanel.SCREEN_WIDTH - 2 * OFFSET_X) / MAP_TILESIZE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package se.urmo.game.state;
|
||||
|
||||
import lombok.Getter;
|
||||
import se.urmo.game.main.Game;
|
||||
|
||||
import java.awt.*;
|
||||
@ -9,6 +10,7 @@ import java.util.Map;
|
||||
public class GameStateManager {
|
||||
private final Game game;
|
||||
private Map<GameStateType, GameState> states = new HashMap<>();
|
||||
@Getter
|
||||
private GameState currentState;
|
||||
|
||||
public GameStateManager(Game game) {
|
||||
@ -28,8 +30,4 @@ public class GameStateManager {
|
||||
public void render(Graphics2D g) {
|
||||
currentState.render(g);
|
||||
}
|
||||
|
||||
public GameState getCurrentState() {
|
||||
return currentState;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
package se.urmo.game.state;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import se.urmo.game.collision.GhostCollisionChecker;
|
||||
import se.urmo.game.entities.BlinkyStrategy;
|
||||
import se.urmo.game.entities.Ghost;
|
||||
import se.urmo.game.entities.GhostMode;
|
||||
import se.urmo.game.entities.PacMan;
|
||||
import se.urmo.game.entities.PinkyStrategy;
|
||||
import se.urmo.game.entities.ScatterToTopRight;
|
||||
import se.urmo.game.map.GameMap;
|
||||
import se.urmo.game.util.LoadSave;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
@ -14,21 +17,34 @@ import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
public class GhostManager {
|
||||
public static final int SPRITE_SHEET_ROWS = 10;
|
||||
public static final int MAX_SPRITE_FRAMES = 4;
|
||||
@Getter
|
||||
private final List<Ghost> ghosts = new ArrayList<>();
|
||||
private BufferedImage[][] image;
|
||||
private GhostMode globalMode = GhostMode.CHASE;
|
||||
private GhostMode globalMode;
|
||||
|
||||
private long lastModeSwitchTime;
|
||||
private int phaseIndex = 0;
|
||||
|
||||
// cycle in milliseconds: {scatter, chase, scatter, chase, ...}
|
||||
private final int[] cycleDurations = {
|
||||
7000, 20000, // scatter 7s, chase 20s
|
||||
7000, 20000, // scatter 7s, chase 20s
|
||||
5000, 20000, // scatter 5s, chase 20s
|
||||
5000, Integer.MAX_VALUE // scatter 5s, then chase forever
|
||||
};
|
||||
|
||||
public GhostManager(GhostCollisionChecker ghostCollisionChecker) {
|
||||
loadAnimation();
|
||||
// Create ghosts with their strategies
|
||||
//ghosts.add(new Ghost(ghostCollisionChecker, new BlinkyStrategy(),image[0]));
|
||||
//ghosts.add(new Ghost(ghostCollisionChecker, new PinkyStrategy(), image[1]));
|
||||
ghosts.add(new Ghost(ghostCollisionChecker, new BlinkyStrategy(),new ScatterToTopLeft(), image[0]));
|
||||
ghosts.add(new Ghost(ghostCollisionChecker, new PinkyStrategy(),new ScatterToTopRight(), image[1]));
|
||||
//ghosts.add(new Ghost(240, 200, new InkyStrategy(), loader.getSprite("inky")));
|
||||
//ghosts.add(new Ghost(260, 200, new ClydeStrategy(), loader.getSprite("clyde")));
|
||||
setMode(GhostMode.CHASE);
|
||||
}
|
||||
|
||||
private void loadAnimation() {
|
||||
@ -44,14 +60,28 @@ public class GhostManager {
|
||||
|
||||
public void setMode(GhostMode mode) {
|
||||
this.globalMode = mode;
|
||||
log.debug("Mode changed to {}", globalMode);
|
||||
for (Ghost g : ghosts) {
|
||||
g.setMode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(PacMan pacman) {
|
||||
public void update(PacMan pacman, GameMap map) {
|
||||
long now = System.currentTimeMillis();
|
||||
if (phaseIndex < cycleDurations.length) {
|
||||
int duration = cycleDurations[phaseIndex];
|
||||
if (now - lastModeSwitchTime >= duration) {
|
||||
phaseIndex++;
|
||||
if (phaseIndex < cycleDurations.length) {
|
||||
GhostMode newMode = (phaseIndex % 2 == 0) ? GhostMode.SCATTER : GhostMode.CHASE;
|
||||
setMode(newMode);
|
||||
}
|
||||
lastModeSwitchTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
for (Ghost g : ghosts) {
|
||||
g.update(pacman);
|
||||
g.update(pacman, map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ public class PlayingState implements GameState {
|
||||
@Override
|
||||
public void update() {
|
||||
pacman.update();
|
||||
ghostManager.update(pacman);
|
||||
ghostManager.update(pacman, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
15
src/main/java/se/urmo/game/state/ScatterToTopLeft.java
Normal file
15
src/main/java/se/urmo/game/state/ScatterToTopLeft.java
Normal file
@ -0,0 +1,15 @@
|
||||
package se.urmo.game.state;
|
||||
|
||||
import se.urmo.game.entities.GhostStrategy;
|
||||
import se.urmo.game.entities.PacMan;
|
||||
import se.urmo.game.map.GameMap;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
public class ScatterToTopLeft implements GhostStrategy {
|
||||
|
||||
@Override
|
||||
public Point chooseTarget(PacMan pacman, GameMap map) {
|
||||
return new Point(1, 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user