Ghosts can get inside their house now
Add Path object for defining apath an entity should take at a given speed. Fix some issues with ghost capturing logic
This commit is contained in:
parent
2a65084363
commit
cd2b968631
@ -15,6 +15,8 @@ public class PacDude extends Game {
|
||||
public static final String TITLE = "Pac-Dude";
|
||||
public static final String VERSION = "v0.0.1";
|
||||
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
public static final int LEVEL_WIDTH = 224;
|
||||
public static final int LEVEL_HEIGHT = 288;
|
||||
|
||||
|
@ -4,42 +4,51 @@ import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
public enum Direction {
|
||||
|
||||
UP,
|
||||
DOWN,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
UP(new Vector2(0f, 1f)),
|
||||
DOWN(new Vector2(0f, -1f)),
|
||||
LEFT(new Vector2(-1f, 0f)),
|
||||
RIGHT(new Vector2(1f, 0f)),
|
||||
;
|
||||
|
||||
public boolean isOpposite(Direction dir) {
|
||||
private Vector2 vector;
|
||||
|
||||
Direction(Vector2 vector) {
|
||||
this.vector = vector;
|
||||
}
|
||||
|
||||
public Direction getOpposite() {
|
||||
switch (this) {
|
||||
case UP:
|
||||
return dir == DOWN;
|
||||
return DOWN;
|
||||
case DOWN:
|
||||
return dir == UP;
|
||||
return UP;
|
||||
case LEFT:
|
||||
return dir == RIGHT;
|
||||
return RIGHT;
|
||||
case RIGHT:
|
||||
return dir == LEFT;
|
||||
return LEFT;
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isOpposite(Direction dir) {
|
||||
return dir == getOpposite();
|
||||
}
|
||||
|
||||
public Vector2 getVector(float scale) {
|
||||
switch (this) {
|
||||
case UP:
|
||||
return new Vector2(0f, 1f * scale);
|
||||
case DOWN:
|
||||
return new Vector2(0f, -1f * scale);
|
||||
case LEFT:
|
||||
return new Vector2(-1 * scale, 0f);
|
||||
case RIGHT:
|
||||
return new Vector2(1 * scale, 0f);
|
||||
}
|
||||
return null;
|
||||
return new Vector2(this.vector).scl(scale);
|
||||
}
|
||||
|
||||
public Vector2 getVector() {
|
||||
return this.getVector(1f);
|
||||
}
|
||||
|
||||
public static Direction fromVector(Vector2 vector) {
|
||||
for (Direction dir : values()) {
|
||||
if (dir.vector.hasSameDirection(vector)) {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import com.badlogic.gdx.math.Vector2;
|
||||
import com.me.pacman.entity.ai.Behaviour;
|
||||
import com.me.pacman.entity.ai.ReturnToBase;
|
||||
import com.me.pacman.entity.ai.Target;
|
||||
import com.me.pacman.entity.path.EnterGhostHousePath;
|
||||
import com.me.pacman.entity.path.ExitGhostHousePath;
|
||||
import com.me.pacman.level.LevelTile;
|
||||
import com.me.pacman.state.PlayState;
|
||||
|
||||
@ -13,6 +15,10 @@ import java.util.ArrayList;
|
||||
|
||||
public class Ghost extends MovableEntity {
|
||||
|
||||
public static final float GHOST_SPEED = 7.03f;
|
||||
public static final float GHOST_TUNNEL_SPEED = GHOST_SPEED / 2;
|
||||
public static final float EYES_SPEED = 15f;
|
||||
|
||||
public static final Direction[] GHOST_ORDER = { Direction.UP, Direction.LEFT, Direction.DOWN, Direction.RIGHT };
|
||||
|
||||
private PlayState state;
|
||||
@ -32,7 +38,7 @@ public class Ghost extends MovableEntity {
|
||||
|
||||
public Ghost(PlayState state, float x, float y, Direction direction, int spriteIndex,
|
||||
Behaviour chaseBehaviour, Behaviour scatterBehaviour) {
|
||||
super(state, x, y, 7.03f, true, direction, 0.1f);
|
||||
super(state, x, y, GHOST_SPEED, true, direction, 0.1f);
|
||||
this.state = state;
|
||||
this.spriteIndex = spriteIndex;
|
||||
this.chaseBehaviour = chaseBehaviour;
|
||||
@ -45,7 +51,7 @@ public class Ghost extends MovableEntity {
|
||||
|
||||
@Override
|
||||
public TextureRegion getSprite() {
|
||||
if (caught) {
|
||||
if (caught && !returned) {
|
||||
return null;
|
||||
} else if (state.frightTimer > 0 && !returned) {
|
||||
return sprite[0][counter % 2];
|
||||
@ -71,6 +77,23 @@ public class Ghost extends MovableEntity {
|
||||
counter++;
|
||||
}
|
||||
|
||||
if (currentPath != null) {
|
||||
if (currentPath instanceof EnterGhostHousePath) {
|
||||
if (!currentPath.finished()) {
|
||||
return;
|
||||
}
|
||||
currentPath = new ExitGhostHousePath(pos);
|
||||
returned = true;
|
||||
} else if (currentPath instanceof ExitGhostHousePath) {
|
||||
if (!currentPath.finished()) {
|
||||
return;
|
||||
}
|
||||
speed = GHOST_SPEED;
|
||||
currentBehaviour = chaseBehaviour;
|
||||
currentPath = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentBehaviour == null) {
|
||||
return;
|
||||
}
|
||||
@ -86,9 +109,8 @@ public class Ghost extends MovableEntity {
|
||||
}
|
||||
|
||||
if (currentBehaviour instanceof ReturnToBase && target.targetReached(pos)) {
|
||||
caught = false;
|
||||
returned = true;
|
||||
currentBehaviour = chaseBehaviour;
|
||||
currentPath = new EnterGhostHousePath(pos);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 ahead = new Vector2((int) pos.x, (int) pos.y).add(currDirection.getVector());
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.me.pacman.entity;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.me.pacman.entity.path.Path;
|
||||
import com.me.pacman.level.LevelTile;
|
||||
import com.me.pacman.state.LevelState;
|
||||
|
||||
@ -15,6 +16,8 @@ public abstract class MovableEntity extends Entity {
|
||||
private Direction nextDirection = null;
|
||||
public boolean canMove = true;
|
||||
|
||||
public Path currentPath = null;
|
||||
|
||||
public MovableEntity(LevelState state, float x, float y, float speed, boolean moving, Direction currDirection, float turnTolerance) {
|
||||
super(state, x, y);
|
||||
this.speed = speed;
|
||||
@ -30,6 +33,12 @@ public abstract class MovableEntity extends Entity {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentPath != null) {
|
||||
currentPath.update(dt);
|
||||
currentPath.updateEntity(this);
|
||||
return;
|
||||
}
|
||||
|
||||
LevelTile nextTile = null;
|
||||
|
||||
if (nextDirection != null) {
|
||||
@ -89,8 +98,6 @@ public abstract class MovableEntity extends Entity {
|
||||
float dist = speed * dt;
|
||||
|
||||
LevelTile currentTile = state.level.getTile(pos.x, pos.y);
|
||||
nextTile = null;
|
||||
|
||||
Vector2 new_pos = new Vector2(pos);
|
||||
|
||||
switch (currDirection) {
|
||||
|
@ -4,7 +4,6 @@ import com.me.pacman.state.PlayState;
|
||||
|
||||
public class ReturnToBase extends Behaviour {
|
||||
|
||||
// final Target home = new Target(14, 16);
|
||||
final Target home = new Target(14, 19);
|
||||
|
||||
public ReturnToBase(PlayState state) {
|
||||
|
20
core/src/com/me/pacman/entity/path/EnterGhostHousePath.java
Normal file
20
core/src/com/me/pacman/entity/path/EnterGhostHousePath.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com.me.pacman.entity.path;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.me.pacman.entity.Ghost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class EnterGhostHousePath extends Path {
|
||||
|
||||
private static final ArrayList<Vector2> points = new ArrayList<Vector2>() {{
|
||||
add(new Vector2(14, 19.5f));
|
||||
add(new Vector2(14, 16.5f));
|
||||
}};
|
||||
|
||||
public EnterGhostHousePath(Vector2 start) {
|
||||
super(Ghost.EYES_SPEED, start);
|
||||
addPoints(points);
|
||||
}
|
||||
|
||||
}
|
20
core/src/com/me/pacman/entity/path/ExitGhostHousePath.java
Normal file
20
core/src/com/me/pacman/entity/path/ExitGhostHousePath.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com.me.pacman.entity.path;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.me.pacman.entity.Ghost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ExitGhostHousePath extends Path {
|
||||
|
||||
private static final ArrayList<Vector2> points = new ArrayList<Vector2>() {{
|
||||
add(new Vector2(14, 16.5f));
|
||||
add(new Vector2(14, 19.5f));
|
||||
}};
|
||||
|
||||
public ExitGhostHousePath(Vector2 start) {
|
||||
super(Ghost.GHOST_TUNNEL_SPEED, start);
|
||||
addPoints(points);
|
||||
}
|
||||
|
||||
}
|
89
core/src/com/me/pacman/entity/path/Path.java
Normal file
89
core/src/com/me/pacman/entity/path/Path.java
Normal file
@ -0,0 +1,89 @@
|
||||
package com.me.pacman.entity.path;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.me.pacman.entity.Direction;
|
||||
import com.me.pacman.entity.MovableEntity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Path {
|
||||
|
||||
private float speed; // speed in tiles/sec
|
||||
private float elapsed; // seconds elapsed since beginning of path
|
||||
|
||||
private List<Vector2> points; // points in the path
|
||||
private List<Float> segmentLengths;
|
||||
private int pathSegments; // total path segments
|
||||
|
||||
private float pathLength; // total path length
|
||||
private float progress; // distance along path
|
||||
|
||||
public Path(float speed, Vector2 start) {
|
||||
this.speed = speed;
|
||||
this.elapsed = 0;
|
||||
this.points = new ArrayList<>();
|
||||
this.segmentLengths = new ArrayList<>();
|
||||
addPoint(start);
|
||||
}
|
||||
|
||||
public void addPoints(List<Vector2> points) {
|
||||
for (Vector2 point : points) {
|
||||
addPoint(point);
|
||||
}
|
||||
}
|
||||
|
||||
protected void addPoint(Vector2 point) {
|
||||
points.add(point);
|
||||
|
||||
if (points.size() == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
pathSegments++;
|
||||
Vector2 previous = points.get(points.size()-2);
|
||||
float length = previous.dst(point);
|
||||
segmentLengths.add(length);
|
||||
pathLength += length;
|
||||
}
|
||||
|
||||
public void updateEntity(MovableEntity entity) {
|
||||
if (finished()) {
|
||||
return;
|
||||
}
|
||||
|
||||
float tmp = progress;
|
||||
for (int i = 0; i < pathSegments; i++) {
|
||||
float segmentLength = segmentLengths.get(i);
|
||||
|
||||
if (tmp > segmentLength) {
|
||||
tmp -= segmentLength;
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector2 a = new Vector2(points.get(i));
|
||||
Vector2 b = new Vector2(points.get(i+1));
|
||||
|
||||
Vector2 pathDir = b.sub(a).nor();
|
||||
|
||||
entity.currDirection = Direction.fromVector(pathDir);
|
||||
entity.pos = a.add(pathDir.scl(tmp));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
elapsed = 0;
|
||||
progress = 0;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return progress >= pathLength;
|
||||
}
|
||||
|
||||
public void update(float dt) {
|
||||
elapsed += dt;
|
||||
progress = elapsed * speed;
|
||||
}
|
||||
|
||||
}
|
@ -106,6 +106,11 @@ public class PlayState extends LevelState {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PacDude.DEBUG) {
|
||||
// Fixed time step for debugger
|
||||
dt = 1/60f;
|
||||
}
|
||||
|
||||
if (gameOverTimer > 0) {
|
||||
gameOverTimer -= dt;
|
||||
if (gameOverTimer <= 0) {
|
||||
@ -137,7 +142,8 @@ public class PlayState extends LevelState {
|
||||
frightTimer -= dt;
|
||||
if (frightTimer < 0) {
|
||||
for (Ghost ghost : ghosts) {
|
||||
if (ghost == null || ghost.caught) continue;
|
||||
if (ghost == null || (ghost.caught && !ghost.returned)) continue;
|
||||
ghost.caught = false;
|
||||
ghost.currentBehaviour = ghost.chaseBehaviour;
|
||||
}
|
||||
}
|
||||
@ -151,7 +157,7 @@ public class PlayState extends LevelState {
|
||||
ghost.update(dt);
|
||||
|
||||
if (ghost.onSameTile(pacman)) {
|
||||
if (frightTimer > 0) {
|
||||
if (frightTimer > 0 && !ghost.returned) {
|
||||
if (!ghost.caught) ghostCaught(ghost);
|
||||
} else {
|
||||
pacmanCaught();
|
||||
@ -268,6 +274,7 @@ public class PlayState extends LevelState {
|
||||
if (ghost == null || ghost.caught) continue;
|
||||
ghost.currentBehaviour = ghost.frightBehaviour;
|
||||
ghost.returned = false;
|
||||
ghost.currDirection = ghost.currDirection.getOpposite();
|
||||
}
|
||||
frightTimer = 6f;
|
||||
score += 50;
|
||||
@ -284,6 +291,7 @@ public class PlayState extends LevelState {
|
||||
ghost.caught = true;
|
||||
ghost.returned = false;
|
||||
ghost.currentBehaviour = new ReturnToBase(this);
|
||||
ghost.speed = Ghost.EYES_SPEED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user