Implement FrightBehaviour

This took way too long.
This commit is contained in:
Matt Low 2019-12-26 16:13:29 +04:00
parent 75d0c41bb5
commit afad1017a5
4 changed files with 84 additions and 18 deletions

View File

@ -8,6 +8,8 @@ import com.me.pacman.entity.ai.Target;
import com.me.pacman.level.LevelTile; import com.me.pacman.level.LevelTile;
import com.me.pacman.state.PlayState; import com.me.pacman.state.PlayState;
import java.util.ArrayList;
public class Ghost extends MovableEntity { 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 };
@ -17,8 +19,8 @@ public class Ghost extends MovableEntity {
public Behaviour currentBehaviour; public Behaviour currentBehaviour;
public Behaviour chaseBehaviour; public Behaviour chaseBehaviour;
public Behaviour freightBehaviour;
public Behaviour scatterBehaviour; public Behaviour scatterBehaviour;
public Behaviour frightBehaviour;
public TextureRegion[][] sprite; public TextureRegion[][] sprite;
@ -26,13 +28,13 @@ public class Ghost extends MovableEntity {
private int counter = 0; 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 freightBehaviour, Behaviour scatterBehaviour) { Behaviour chaseBehaviour, Behaviour scatterBehaviour) {
super(state, x, y, 7.03f, true, direction, 0.1f); super(state, x, y, 7.03f, true, direction, 0.1f);
this.state = state; this.state = state;
this.spriteIndex = spriteIndex; this.spriteIndex = spriteIndex;
this.chaseBehaviour = chaseBehaviour; this.chaseBehaviour = chaseBehaviour;
this.freightBehaviour = freightBehaviour;
this.scatterBehaviour = scatterBehaviour; this.scatterBehaviour = scatterBehaviour;
this.frightBehaviour = new FrightenedBehaviour(state);
sprite = state.getGame().assets.ghosts; sprite = state.getGame().assets.ghosts;
} }
@ -53,7 +55,7 @@ public class Ghost extends MovableEntity {
public void update(float dt) { public void update(float dt) {
super.update(dt); super.update(dt);
if (!state.paused && age % 20 == 0) { if (age % 20 == 0) {
counter++; counter++;
} }
@ -66,16 +68,19 @@ public class Ghost extends MovableEntity {
} }
Target target = currentBehaviour.getTarget(); Target target = currentBehaviour.getTarget();
Vector2 ahead = new Vector2((int) pos.x, (int) pos.y).add(currDirection.getVector()); if (target == null) {
// no target, carry on current course
return;
}
Direction bestDirection = null; Vector2 ahead = new Vector2((int) pos.x, (int) pos.y).add(currDirection.getVector());
float shortest = Float.MAX_VALUE; float shortest = Float.MAX_VALUE;
Direction nextDirection = null;
for (Direction dir : GHOST_ORDER) { for (Direction dir : GHOST_ORDER) {
if (dir.isOpposite(currDirection)) { if (dir.isOpposite(currDirection)) {
continue; continue;
} }
Vector2 adjacent = dir.getVector().add(ahead); Vector2 adjacent = dir.getVector().add(ahead);
LevelTile nextTile = state.level.getTile(adjacent); LevelTile nextTile = state.level.getTile(adjacent);
if (nextTile != null && nextTile.isPassable()) { if (nextTile != null && nextTile.isPassable()) {
@ -83,14 +88,12 @@ public class Ghost extends MovableEntity {
float d = target.distance_sqr(adjacent); float d = target.distance_sqr(adjacent);
if (d < shortest) { if (d < shortest) {
shortest = d; shortest = d;
bestDirection = dir; nextDirection = dir;
} }
} }
} }
if (bestDirection != null) { setNextDirection(nextDirection);
setNextDirection(bestDirection);
}
} }
private class ReturnToBase extends Behaviour { private class ReturnToBase extends Behaviour {
@ -108,4 +111,56 @@ public class Ghost extends MovableEntity {
} }
private class FrightenedBehaviour extends Behaviour {
private Target target;
public FrightenedBehaviour(PlayState state) {
super(state);
}
@Override
public Target getTarget() {
if (target != null && !target.targetReached(pos)) {
return target;
}
ArrayList<Vector2> adjacentTiles = new ArrayList<>(3);
ArrayList<Direction> possibleTurns = new ArrayList<>(3);
Vector2 ahead = new Vector2((int) pos.x, (int) pos.y).add(currDirection.getVector());
for (Direction dir : GHOST_ORDER) {
if (dir.isOpposite(currDirection)) {
// Don't consider going backwards
continue;
}
Vector2 adjacent = dir.getVector().add(ahead);
LevelTile nextTile = state.level.getTile(adjacent);
if (nextTile != null && nextTile.isPassable()) {
adjacentTiles.add(adjacent);
possibleTurns.add(dir);
}
}
if (possibleTurns.size() == 0) {
// No possible turns means no valid tiles ahead, which would be the tunnel.
target = null;
} else if (possibleTurns.size() == 1) {
if (possibleTurns.get(0) == currDirection) {
// can only go straight, so no target
target = null;
} else {
// turn the only possible direction
target = new Target(adjacentTiles.get(0));
}
} else {
// n-way intersection, pick random direction
int rand = state.random.nextInt(adjacentTiles.size());
target = new Target(adjacentTiles.get(rand));
}
return target;
}
}
} }

View File

@ -46,11 +46,11 @@ public class Pacman extends MovableEntity {
super.update(dt); super.update(dt);
if (!state.paused && canMove && age % 4 == 0) { if (canMove && age % 4 == 0) {
counter += 1; counter += 1;
} }
if (age % 8 == 0 && !alive) { if (!alive && age % 8 == 0) {
deathFrame++; deathFrame++;
} }

View File

@ -32,4 +32,8 @@ public class Target {
return this.x == (int) x && this.y == (int) y; return this.x == (int) x && this.y == (int) y;
} }
public boolean targetReached(Vector2 vec) {
return targetReached(vec.x, vec.y);
}
} }

View File

@ -15,17 +15,21 @@ import com.me.pacman.entity.ai.BlinkyChaseBehaviour;
import com.me.pacman.level.Level; import com.me.pacman.level.Level;
import com.me.pacman.level.LevelTile; import com.me.pacman.level.LevelTile;
import java.util.Random;
public class PlayState extends LevelState { public class PlayState extends LevelState {
private Texture levelBackground; private Texture levelBackground;
private BitmapFont font; private BitmapFont font;
private TextureRegion lifeSprite;
private int pelletCount; private int pelletCount;
private int pelletEatenCount; private int pelletEatenCount;
private int score; private int score;
private int lives; private int lives;
private int round; private int round;
public boolean paused = false; private boolean paused = false;
private long sirenId; private long sirenId;
@ -36,7 +40,7 @@ public class PlayState extends LevelState {
private boolean pacmanCaught; private boolean pacmanCaught;
private TextureRegion lifeSprite; public Random random;
public Pacman pacman; public Pacman pacman;
public Ghost[] ghosts; public Ghost[] ghosts;
@ -90,7 +94,6 @@ public class PlayState extends LevelState {
if (paused) { if (paused) {
game.assets.getFont().setColor(Color.YELLOW); game.assets.getFont().setColor(Color.YELLOW);
game.assets.getFont().draw(game.batch, "paused", 90, 151); game.assets.getFont().draw(game.batch, "paused", 90, 151);
return;
} }
} }
@ -127,6 +130,8 @@ public class PlayState extends LevelState {
} }
} }
dt = 1/60f;
if (!pacmanCaught) { if (!pacmanCaught) {
for (Ghost ghost : ghosts) { for (Ghost ghost : ghosts) {
if (ghost == null) { if (ghost == null) {
@ -184,7 +189,7 @@ public class PlayState extends LevelState {
level = new Level(game,"level"); level = new Level(game,"level");
pacman = new Pacman(this, false); pacman = new Pacman(this, false);
ghosts[0] = new Ghost(this, 14, 19.5f, Direction.LEFT, 0, new BlinkyChaseBehaviour(this), null, null); ghosts[0] = new Ghost(this, 14, 19.5f, Direction.LEFT, 0, new BlinkyChaseBehaviour(this), null);
ghosts[0].currentBehaviour = ghosts[0].chaseBehaviour; ghosts[0].currentBehaviour = ghosts[0].chaseBehaviour;
game.assets.siren.stop(sirenId); game.assets.siren.stop(sirenId);
@ -205,8 +210,10 @@ public class PlayState extends LevelState {
lives--; lives--;
pacmanCaught = false; pacmanCaught = false;
random = new Random(897198256012865L);
pacman = new Pacman(this, false); pacman = new Pacman(this, false);
ghosts[0] = new Ghost(this, 14, 19.5f, Direction.LEFT, 0, new BlinkyChaseBehaviour(this), null, null); ghosts[0] = new Ghost(this, 14, 19.5f, Direction.LEFT, 0, new BlinkyChaseBehaviour(this), null);
ghosts[0].currentBehaviour = ghosts[0].chaseBehaviour; ghosts[0].currentBehaviour = ghosts[0].chaseBehaviour;
} }