There's a ghost! And death. And a game over sequence.

This commit is contained in:
Matt Low 2019-12-26 01:44:10 +04:00
parent 6073c6c84a
commit 1153205ddd
7 changed files with 248 additions and 43 deletions

View File

@ -2,7 +2,7 @@ package com.me.pacman.entity;
public enum Direction { public enum Direction {
NORTH, NORTH,
EAST,
SOUTH, SOUTH,
WEST WEST,
EAST,
} }

View File

@ -22,6 +22,10 @@ public abstract class Entity {
batch.draw(getSprite(), (int) (x * 8) + (offsetX - 8), (y * 8) + (offsetY - 8)); batch.draw(getSprite(), (int) (x * 8) + (offsetX - 8), (y * 8) + (offsetY - 8));
} }
public boolean onSameTile(Entity other) {
return (int) x == (int) other.x && (int) y == (int) other.y;
}
public abstract TextureRegion getSprite(); public abstract TextureRegion getSprite();
public void update(float dt) { public void update(float dt) {

View File

@ -0,0 +1,72 @@
package com.me.pacman.entity;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.me.pacman.entity.ai.Behaviour;
import com.me.pacman.entity.ai.Target;
import com.me.pacman.state.PlayState;
public class Ghost extends MovableEntity {
private PlayState state;
public Behaviour currentBehaviour;
public Behaviour chaseBehaviour;
public Behaviour freightBehaviour;
public Behaviour scatterBehaviour;
public TextureRegion[][] sprite;
private int spriteIndex;
private int counter = 0;
public Ghost(PlayState state, float x, float y, Direction direction, int spriteIndex,
Behaviour chaseBehaviour, Behaviour freightBehaviour, Behaviour scatterBehaviour) {
super(state, x, y, 7.33f, true, direction, 0.1f);
this.state = state;
this.spriteIndex = spriteIndex;
this.chaseBehaviour = chaseBehaviour;
this.freightBehaviour = freightBehaviour;
this.scatterBehaviour = scatterBehaviour;
sprite = state.getGame().assets.ghosts;
}
@Override
public TextureRegion getSprite() {
return sprite[2 + (counter % 2)][spriteIndex];
}
@Override
public void render(SpriteBatch batch, int offsetX, int offsetY) {
super.render(batch, offsetX, offsetY);
// draw eyes so the ghost can see
batch.draw(sprite[1][currDirection.ordinal()], (int) (x * 8) + (offsetX - 8), (y * 8) + (offsetY - 8));
}
@Override
public void update(float dt) {
super.update(dt);
if (!state.paused && age % 20 == 0) {
counter++;
}
}
private class ReturnToBase extends Behaviour {
final Target home = new Target(14, 16);
public ReturnToBase(PlayState state) {
super(state);
}
@Override
public Target getTarget() {
return home;
}
}
}

View File

@ -7,40 +7,34 @@ import com.me.pacman.state.PlayState;
public class Pacman extends MovableEntity { public class Pacman extends MovableEntity {
private TextureRegion[][] sprite; private TextureRegion[][] sprite;
private TextureRegion[][] death;
private PlayState state; private PlayState state;
private int counter = 1; private int counter = 1;
private int freezeFrames = 0; private int freezeFrames = 0;
public boolean alive = true;
public int deathFrame = 0;
public Pacman(PlayState state, boolean moving) { public Pacman(PlayState state, boolean moving) {
super(state, 14, 7.5f, 7.5f, moving, Direction.EAST, 0.3f); super(state, 14, 7.5f, 7.5f, moving, Direction.EAST, 0.3f);
this.state = state; this.state = state;
sprite = state.getGame().assets.pacman; sprite = state.getGame().assets.pacman;
death = state.getGame().assets.deathAnimation;
} }
@Override @Override
public TextureRegion getSprite() { public TextureRegion getSprite() {
if (!alive) {
return death[deathFrame / 4][deathFrame % 4];
}
if (!moving) { if (!moving) {
return sprite[2][0]; return sprite[2][0];
} }
int spriteDir; return sprite[currDirection.ordinal()][canMove ? counter % 3 : 1];
switch(currDirection) {
case NORTH:
spriteDir = 0;
break;
case SOUTH:
spriteDir = 1;
break;
case WEST:
spriteDir = 2;
break;
default:
spriteDir = 3;
break;
}
return sprite[spriteDir][canMove ? counter % 3 : 1];
} }
@Override @Override
@ -56,6 +50,10 @@ public class Pacman extends MovableEntity {
counter += 1; counter += 1;
} }
if (age % 8 == 0 && !alive) {
deathFrame++;
}
LevelTile tile = state.level.getTile(x, y); LevelTile tile = state.level.getTile(x, y);
if (tile == null) { if (tile == null) {
return; return;

View File

@ -0,0 +1,15 @@
package com.me.pacman.entity.ai;
import com.me.pacman.state.PlayState;
public abstract class Behaviour {
public PlayState state;
public Behaviour(PlayState state) {
this.state = state;
}
public abstract Target getTarget();
}

View File

@ -0,0 +1,22 @@
package com.me.pacman.entity.ai;
public class Target {
public int x;
public int y;
public Target(int x, int y) {
this.x = x;
this.y = y;
}
public Target(float x, float y) {
this.x = (int) x;
this.y = (int) y;
}
public boolean targetReached(float x, float y) {
return this.x == (int) x && this.y == (int) y;
}
}

View File

@ -3,12 +3,14 @@ package com.me.pacman.state;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input; import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputAdapter; import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.me.pacman.PacDude; import com.me.pacman.PacDude;
import com.me.pacman.entity.Direction; import com.me.pacman.entity.Direction;
import com.me.pacman.entity.Ghost;
import com.me.pacman.entity.Pacman; import com.me.pacman.entity.Pacman;
import com.me.pacman.level.Level; import com.me.pacman.level.Level;
import com.me.pacman.level.LevelTile; import com.me.pacman.level.LevelTile;
@ -27,11 +29,17 @@ public class PlayState extends LevelState {
private long sirenId; private long sirenId;
private float waitTimer; private float readyTimer;
private float gameOverTimer;
private float newGameTimer;
private float deathTimer;
private boolean pacmanCaught;
private TextureRegion lifeSprite; private TextureRegion lifeSprite;
private Pacman pacman; public Pacman pacman;
public Ghost[] ghosts;
public PlayState(PacDude game) { public PlayState(PacDude game) {
super(game); super(game);
@ -44,12 +52,6 @@ public class PlayState extends LevelState {
lifeSprite = game.assets.pacman[2][1]; lifeSprite = game.assets.pacman[2][1];
Gdx.input.setInputProcessor(new Controller()); Gdx.input.setInputProcessor(new Controller());
pelletCount = 0;
pelletEatenCount = 0;
score = 0;
lives = 3;
round = 0;
newGame(); newGame();
} }
@ -66,9 +68,23 @@ public class PlayState extends LevelState {
pacman.render(game.batch, 0, 16); pacman.render(game.batch, 0, 16);
if (waitTimer > 0) { if (pacman.alive) {
for (Ghost ghost : ghosts) {
if (ghost == null) {
continue;
}
ghost.render(game.batch, 0, 16);
}
}
if (readyTimer > 0) {
game.assets.getFont().setColor(Color.YELLOW); game.assets.getFont().setColor(Color.YELLOW);
game.assets.getFont().draw(game.batch, "ready!", 90, 127); game.assets.getFont().draw(game.batch, "ready!", 92, 127);
}
if (gameOverTimer > 0) {
game.assets.getFont().setColor(Color.RED);
game.assets.getFont().draw(game.batch, "game over", 78, 127);
} }
if (paused) { if (paused) {
@ -84,45 +100,115 @@ public class PlayState extends LevelState {
return; return;
} }
if (waitTimer > 0) { if (gameOverTimer > 0) {
waitTimer -= dt; gameOverTimer -= dt;
if (waitTimer <= 0) { if (gameOverTimer <= 0) {
startGame(); newGame();
} else { } else {
return; return;
} }
} }
if (readyTimer > 0) {
readyTimer -= dt;
if (readyTimer <= 0) {
startGame();
} else if (newGameTimer <= 0) {
return;
}
}
if (newGameTimer > 0) {
newGameTimer -= dt;
if (newGameTimer <= 0) {
setupGame();
} else {
return;
}
}
if (!pacmanCaught) {
for (Ghost ghost : ghosts) {
if (ghost == null) {
continue;
}
ghost.update(dt);
if (ghost.onSameTile(pacman)) {
pacmanCaught();
return;
}
}
} else if (deathTimer <= 0) {
if (pacman.alive) {
game.assets.deathSound.play(1f);
}
pacman.alive = false;
if (pacman.deathFrame == 13) {
if (lives > 0) {
setupGame();
readyTimer = 3f;
} else {
gameOverTimer = 2f;
}
}
} else {
deathTimer -= dt;
}
pacman.update(dt); pacman.update(dt);
} }
public void newGame() { public void newGame() {
pelletCount = 0;
pelletEatenCount = 0;
score = 0;
lives = 3;
round = 0;
pacmanCaught = false;
deathTimer = 0f;
newGameTimer = 2.3f;
ghosts = new Ghost[4];
pacman = new Pacman(this, false);
newRound();
}
public void newRound() {
round++; round++;
level = new Level(game,"level");
pacman = new Pacman(this, false);
game.assets.siren.stop(sirenId); game.assets.siren.stop(sirenId);
level = new Level(game,"level");
pelletCount = level.getTileCount(LevelTile.PELLET); pelletCount = level.getTileCount(LevelTile.PELLET);
pelletCount += level.getTileCount(LevelTile.POWER_PELLET); pelletCount += level.getTileCount(LevelTile.POWER_PELLET);
if (round == 1) { if (round == 1) {
waitTimer = 4.3f; readyTimer = 4.2f;
game.assets.beginning.play(1.0f);
} else {
waitTimer = 4.2f;
game.assets.beginning_alt.play(1.0f); game.assets.beginning_alt.play(1.0f);
} else {
readyTimer = 4.3f;
game.assets.beginning.play(1.0f);
} }
}
public void setupGame() {
lives--;
pacmanCaught = false;
pacman = new Pacman(this, false); pacman = new Pacman(this, false);
ghosts[0] = new Ghost(this, 14, 19.5f, Direction.WEST, 0, null, null, null);
} }
public void startGame() { public void startGame() {
pacman.moving = true; pacman.moving = true;
game.assets.beginning.stop();
game.assets.beginning_alt.stop();
sirenId = game.assets.siren.loop(1.0f); sirenId = game.assets.siren.loop(1.0f);
if (round == 1) {
lives--;
}
} }
private void pelletEaten(float x, float y) { private void pelletEaten(float x, float y) {
@ -136,7 +222,7 @@ public class PlayState extends LevelState {
pelletCount--; pelletCount--;
if (pelletCount == 0) { if (pelletCount == 0) {
newGame(); newRound();
} }
} }
@ -151,6 +237,14 @@ public class PlayState extends LevelState {
score += 50; score += 50;
} }
private void pacmanCaught() {
game.assets.siren.stop(sirenId);
deathTimer = 1f;
pacmanCaught = true;
pacman.moving = false;
}
@Override @Override
public void dispose() { public void dispose() {
Gdx.input.setInputProcessor(null); Gdx.input.setInputProcessor(null);