Fix (again) and simplify ghost capture logic

Spawn ghosts inside their house
Start a new game by pressing 'n'
This commit is contained in:
Matt Low 2019-12-28 00:47:18 +04:00
parent e38c7a2dea
commit a8e4d2526e
2 changed files with 28 additions and 27 deletions

View File

@ -21,6 +21,10 @@ public class Ghost extends MovableEntity {
public static final Direction[] GHOST_ORDER = { Direction.UP, Direction.LEFT, Direction.DOWN, Direction.RIGHT }; public static final Direction[] GHOST_ORDER = { Direction.UP, Direction.LEFT, Direction.DOWN, Direction.RIGHT };
private TextureRegion[][] sprite;
private int spriteIndex;
private int counter = 0;
private PlayState state; private PlayState state;
public Behaviour currentBehaviour; public Behaviour currentBehaviour;
@ -29,12 +33,7 @@ public class Ghost extends MovableEntity {
public Behaviour scatterBehaviour; public Behaviour scatterBehaviour;
public Behaviour frightBehaviour; public Behaviour frightBehaviour;
public TextureRegion[][] sprite;
public boolean caught; public boolean caught;
public boolean returned;
private int spriteIndex;
private int counter = 0;
public Ghost(PlayState state, float x, float y, Direction direction, int spriteIndex, public Ghost(PlayState state, float x, float y, Direction direction, int spriteIndex,
Behaviour chaseBehaviour, Behaviour scatterBehaviour) { Behaviour chaseBehaviour, Behaviour scatterBehaviour) {
@ -45,15 +44,14 @@ public class Ghost extends MovableEntity {
this.scatterBehaviour = scatterBehaviour; this.scatterBehaviour = scatterBehaviour;
this.frightBehaviour = new FrightenedBehaviour(state); this.frightBehaviour = new FrightenedBehaviour(state);
this.caught = false; this.caught = false;
this.returned = true;
sprite = state.getGame().assets.ghosts; sprite = state.getGame().assets.ghosts;
} }
@Override @Override
public TextureRegion getSprite() { public TextureRegion getSprite() {
if (caught && !returned) { if (currentBehaviour instanceof ReturnToBase) {
return null; return null;
} else if (state.frightTimer > 0 && !returned) { } else if (state.frightTimer > 0 && !caught) {
if (state.frightTimer > 2) { if (state.frightTimer > 2) {
// Render the blue scared ghost // Render the blue scared ghost
return sprite[0][counter % 2]; return sprite[0][counter % 2];
@ -71,7 +69,7 @@ public class Ghost extends MovableEntity {
super.render(batch, offsetX, offsetY); super.render(batch, offsetX, offsetY);
// draw eyes so the ghost can see // draw eyes so the ghost can see
if (state.frightTimer <= 0 || caught || returned) if (state.frightTimer <= 0 || caught)
batch.draw(sprite[1][currDirection.ordinal()], (int) (pos.x * 8) + (offsetX - 8), (pos.y * 8) + (offsetY - 8)); batch.draw(sprite[1][currDirection.ordinal()], (int) (pos.x * 8) + (offsetX - 8), (pos.y * 8) + (offsetY - 8));
} }
@ -90,9 +88,9 @@ public class Ghost extends MovableEntity {
if (currentPath instanceof EnterGhostHousePath) { if (currentPath instanceof EnterGhostHousePath) {
currentPath = new ExitGhostHousePath(pos); currentPath = new ExitGhostHousePath(pos);
returned = true; currentBehaviour = null;
} else if (currentPath instanceof ExitGhostHousePath) {
speed = GHOST_SPEED; speed = GHOST_SPEED;
} else if (currentPath instanceof ExitGhostHousePath) {
currentBehaviour = chaseBehaviour; currentBehaviour = chaseBehaviour;
currentPath = null; currentPath = null;
} }
@ -106,7 +104,6 @@ public class Ghost extends MovableEntity {
if (!canMove) { if (!canMove) {
// we're stuck somewhere, let's change directions to a new valid direction // we're stuck somewhere, let's change directions to a new valid direction
// check if we already have a nextDirection which will get us unstuck // check if we already have a nextDirection which will get us unstuck
if (nextDirection != null) { if (nextDirection != null) {
Vector2 adjacent = nextDirection.getVector().add(pos); Vector2 adjacent = nextDirection.getVector().add(pos);
@ -115,7 +112,7 @@ public class Ghost extends MovableEntity {
return; return;
} }
} }
// we didn't so check other directions
for (Direction dir : GHOST_ORDER) { for (Direction dir : GHOST_ORDER) {
if (dir.isOpposite(currDirection) || dir == currDirection) { if (dir.isOpposite(currDirection) || dir == currDirection) {
// don't just turn around or keep going our current direction (since we'll continue being stuck) // don't just turn around or keep going our current direction (since we'll continue being stuck)
@ -145,10 +142,11 @@ public class Ghost extends MovableEntity {
return; return;
} }
// Rudimentary path finding
// Check all possible turns of the tile immediately in front of us and turn the direction that is closest
// to our target.
Vector2 ahead = new Vector2((int) pos.x, (int) pos.y).add(currDirection.getVector()); Vector2 ahead = new Vector2((int) pos.x, (int) pos.y).add(currDirection.getVector());
float shortest = Float.MAX_VALUE; float shortest = Float.MAX_VALUE;
for (Direction dir : GHOST_ORDER) { for (Direction dir : GHOST_ORDER) {
if (dir.isOpposite(currDirection)) { if (dir.isOpposite(currDirection)) {
continue; continue;
@ -164,7 +162,6 @@ public class Ghost extends MovableEntity {
} }
} }
} }
setNextDirection(nextDirection); setNextDirection(nextDirection);
} }

View File

@ -143,9 +143,9 @@ public class PlayState extends LevelState {
if (frightTimer > 0) { if (frightTimer > 0) {
frightTimer -= dt; frightTimer -= dt;
if (frightTimer < 0) { if (frightTimer <= 0) {
for (Ghost ghost : ghosts) { for (Ghost ghost : ghosts) {
if (ghost == null || (ghost.caught && !ghost.returned)) continue; if (ghost == null || ghost.currentBehaviour instanceof ReturnToBase) continue;
ghost.caught = false; ghost.caught = false;
ghost.currentBehaviour = ghost.chaseBehaviour; ghost.currentBehaviour = ghost.chaseBehaviour;
} }
@ -160,9 +160,9 @@ public class PlayState extends LevelState {
ghost.update(dt); ghost.update(dt);
if (ghost.onSameTile(pacman)) { if (ghost.onSameTile(pacman)) {
if (frightTimer > 0 && !ghost.returned) { if (frightTimer > 0 && !ghost.caught) {
if (!ghost.caught) ghostCaught(ghost); ghostCaught(ghost);
} else { } else if (frightTimer <= 0 || !(ghost.currentBehaviour instanceof ReturnToBase)) {
pacmanCaught(); pacmanCaught();
return; return;
} }
@ -235,6 +235,8 @@ public class PlayState extends LevelState {
lives--; lives--;
pacmanCaught = false; pacmanCaught = false;
frightTimer = 0f;
random = new Random(897198256012865L); random = new Random(897198256012865L);
pacman = new Pacman(this, false); pacman = new Pacman(this, false);
@ -243,9 +245,9 @@ public class PlayState extends LevelState {
public void placeGhosts() { public void placeGhosts() {
ghosts[0] = new Ghost(this, 14, 19.5f, Direction.LEFT, 0, new BlinkyChaseBehaviour(this), new StaticTargetBehaviour(this, BLINKY_SCATTER_TARGET)); ghosts[0] = new Ghost(this, 14, 19.5f, Direction.LEFT, 0, new BlinkyChaseBehaviour(this), new StaticTargetBehaviour(this, BLINKY_SCATTER_TARGET));
ghosts[1] = new Ghost(this, 14, 19.5f, Direction.LEFT, 1, new PinkyChaseBehaviour(this), new StaticTargetBehaviour(this, PINKY_SCATTER_TARGET)); ghosts[1] = new Ghost(this, 14f, 16.5f, Direction.DOWN, 1, new PinkyChaseBehaviour(this), new StaticTargetBehaviour(this, PINKY_SCATTER_TARGET));
ghosts[2] = new Ghost(this, 14, 19.5f, Direction.RIGHT, 2, new InkyChaseBehaviour(this), new StaticTargetBehaviour(this, INKY_SCATTER_TARGET)); ghosts[2] = new Ghost(this, 12f, 16.5f, Direction.UP, 2, new InkyChaseBehaviour(this), new StaticTargetBehaviour(this, INKY_SCATTER_TARGET));
ghosts[3] = new Ghost(this, 14, 19.5f, Direction.RIGHT, 3, new ClydeChaseBehaviour(this), new StaticTargetBehaviour(this, CLYDE_SCATTER_TARGET)); ghosts[3] = new Ghost(this, 16f, 16.5f, Direction.UP, 3, new ClydeChaseBehaviour(this), new StaticTargetBehaviour(this, CLYDE_SCATTER_TARGET));
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
ghosts[i].currentBehaviour = ghosts[i].chaseBehaviour; ghosts[i].currentBehaviour = ghosts[i].chaseBehaviour;
@ -280,9 +282,9 @@ public class PlayState extends LevelState {
public void eatPowerPellet(float x, float y) { public void eatPowerPellet(float x, float y) {
pelletEaten(x, y); pelletEaten(x, y);
for (Ghost ghost : ghosts) { for (Ghost ghost : ghosts) {
if (ghost == null || ghost.caught) continue; if (ghost == null || ghost.currentBehaviour instanceof ReturnToBase) continue;
ghost.caught = false;
ghost.currentBehaviour = ghost.frightBehaviour; ghost.currentBehaviour = ghost.frightBehaviour;
ghost.returned = false;
ghost.currDirection = ghost.currDirection.getOpposite(); ghost.currDirection = ghost.currDirection.getOpposite();
} }
frightTimer = 6f; frightTimer = 6f;
@ -298,7 +300,6 @@ public class PlayState extends LevelState {
private void ghostCaught(Ghost ghost) { private void ghostCaught(Ghost ghost) {
ghost.caught = true; ghost.caught = true;
ghost.returned = false;
ghost.currentBehaviour = new ReturnToBase(this); ghost.currentBehaviour = new ReturnToBase(this);
ghost.speed = Ghost.EYES_SPEED; ghost.speed = Ghost.EYES_SPEED;
} }
@ -328,6 +329,9 @@ public class PlayState extends LevelState {
case Input.Keys.P: case Input.Keys.P:
paused = !paused; paused = !paused;
break; break;
case Input.Keys.N:
newGame();
break;
} }
return super.keyDown(keycode); return super.keyDown(keycode);
} }