Plumb in high scores

This commit is contained in:
Matt Low 2020-01-16 03:54:38 +04:00
parent 0d69521986
commit a9e99a363c
10 changed files with 322 additions and 11 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -18,6 +18,7 @@ public class Assets {
private Texture levelBackground; private Texture levelBackground;
private Texture levelWinBackground; private Texture levelWinBackground;
private Texture menuBackground; private Texture menuBackground;
private Texture highScoresBackground;
public TextureRegion[][] font; public TextureRegion[][] font;
public TextureRegion[][] level; public TextureRegion[][] level;
@ -44,6 +45,7 @@ public class Assets {
manager.load("level_background.png", Texture.class); manager.load("level_background.png", Texture.class);
manager.load("level_background_win.png", Texture.class); manager.load("level_background_win.png", Texture.class);
manager.load("menu_background.png", Texture.class); manager.load("menu_background.png", Texture.class);
manager.load("high_scores_background.png", Texture.class);
manager.load("logo.png", Texture.class); manager.load("logo.png", Texture.class);
manager.load("sprites/font.png", Texture.class); manager.load("sprites/font.png", Texture.class);
@ -75,6 +77,7 @@ public class Assets {
levelBackground = manager.get("level_background.png", Texture.class); levelBackground = manager.get("level_background.png", Texture.class);
levelWinBackground = manager.get("level_background_win.png", Texture.class); levelWinBackground = manager.get("level_background_win.png", Texture.class);
menuBackground = manager.get("menu_background.png", Texture.class); menuBackground = manager.get("menu_background.png", Texture.class);
highScoresBackground = manager.get("high_scores_background.png", Texture.class);
// cache our texture regions // cache our texture regions
font = TextureRegion.split(manager.get("sprites/font.png", Texture.class), 8, 8); font = TextureRegion.split(manager.get("sprites/font.png", Texture.class), 8, 8);
@ -114,6 +117,8 @@ public class Assets {
return menuBackground; return menuBackground;
} }
public Texture getHighScoresBackground() { return highScoresBackground; }
public Texture getLogo() { public Texture getLogo() {
return manager.get("logo.png", Texture.class); return manager.get("logo.png", Texture.class);
} }

View File

@ -7,8 +7,8 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
public class FontRenderer { public class FontRenderer {
private static final char[] CHARS = "abcdefghijklmnopqrstuvwxyz0123456789!?()[]<>$&*:#^~-_/\\".toCharArray(); public static final char[] CHARS = "abcdefghijklmnopqrstuvwxyz0123456789!?()[]<>$&*:#^~-_/\\".toCharArray();
private static final int[] CHAR_TO_INDEX = new int[256]; public static final int[] CHAR_TO_INDEX = new int[256];
private Color color = Color.WHITE; private Color color = Color.WHITE;
private TextureRegion[][] sprites; private TextureRegion[][] sprites;

View File

@ -0,0 +1,67 @@
package com.me.pacman;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
/**
* A simple class for retrieving and saving high scores to persistent storage.
*
* Scores are saved in a simple text file
*/
public class HighScores {
public static final String FILE = "scores.dat";
private FileHandle file;
private Array<Score> scores = new Array<>(10);
public HighScores() {
file = Gdx.files.local(FILE);
loadScores();
}
private void loadScores() {
if (!file.exists()) {
return;
}
String data = file.readString();
String[] lines = data.split("\n");
for (String line : lines) {
String[] parts = line.split("\t");
scores.add(new Score(parts[0], Integer.parseInt(parts[1])));
}
}
private void saveScores() {
for (int i = 0; i < scores.size; i++) {
Score score = scores.get(i);
boolean append = i > 0;
file.writeString(String.format("%s\t%d\n", score.scorer, score.score), append);
}
}
private void sortScores() {
scores.sort(Score.SCORE_SORTER);
}
public Score getCurrentHighScore() {
return scores.size > 0 ? scores.get(0) : null;
}
public Score[] getHighScores(int count) {
Score[] ret = new Score[Math.min(count, scores.size)];
System.arraycopy(scores.items, 0, ret, 0, ret.length);
return ret;
}
public void addScore(Score score) {
scores.add(score);
sortScores();
saveScores();
}
}

View File

@ -2,12 +2,15 @@ package com.me.pacman;
import com.badlogic.gdx.Game; import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.viewport.FitViewport; import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport; import com.badlogic.gdx.utils.viewport.Viewport;
import com.me.pacman.state.HighScoresState;
import com.me.pacman.state.MenuState; import com.me.pacman.state.MenuState;
import com.me.pacman.state.State;
public class PacDude extends Game { public class PacDude extends Game {
@ -19,6 +22,8 @@ public class PacDude extends Game {
public static final int LEVEL_WIDTH = 224; public static final int LEVEL_WIDTH = 224;
public static final int LEVEL_HEIGHT = 288; public static final int LEVEL_HEIGHT = 288;
public HighScores highScores;
public Assets assets; public Assets assets;
public Sound sound; public Sound sound;
@ -28,12 +33,16 @@ public class PacDude extends Game {
public OrthographicCamera cam; public OrthographicCamera cam;
public Viewport viewport; public Viewport viewport;
private State nextState;
@Override @Override
public void create () { public void create () {
cam = new OrthographicCamera(); cam = new OrthographicCamera();
viewport = new FitViewport(LEVEL_WIDTH, LEVEL_HEIGHT, cam); viewport = new FitViewport(LEVEL_WIDTH, LEVEL_HEIGHT, cam);
viewport.apply(true); viewport.apply(true);
highScores = new HighScores();
assets = new Assets(); assets = new Assets();
assets.loadAssets(); assets.loadAssets();
sound = new Sound(this); sound = new Sound(this);
@ -42,13 +51,21 @@ public class PacDude extends Game {
fontRenderer = new FontRenderer(assets.font); fontRenderer = new FontRenderer(assets.font);
Gdx.gl.glClearColor(0, 0, 0, 1); Gdx.gl.glClearColor(0, 0, 0, 1);
setScreen(new MenuState(this)); setNextState(new MenuState(this));
} }
@Override @Override
public void render () { public void render () {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if (nextState != null) {
Screen currScreen = getScreen();
if (currScreen != null) currScreen.dispose();
nextState.setup();
super.setScreen(nextState);
nextState = null;
}
batch.begin(); batch.begin();
if (DEBUG) { if (DEBUG) {
fontRenderer.draw(batch, "fps:" + Gdx.graphics.getFramesPerSecond(), 19 * 8, 34 * 8); fontRenderer.draw(batch, "fps:" + Gdx.graphics.getFramesPerSecond(), 19 * 8, 34 * 8);
@ -71,4 +88,14 @@ public class PacDude extends Game {
batch.dispose(); batch.dispose();
assets.dispose(); assets.dispose();
} }
@Override
public void setScreen(Screen screen) {
throw new IllegalStateException("Use setNextState instead.");
}
public void setNextState(State state) {
this.nextState = state;
}
} }

View File

@ -0,0 +1,22 @@
package com.me.pacman;
import java.util.Comparator;
public final class Score {
public String scorer;
public int score;
public static final Comparator<Score> SCORE_SORTER = new Comparator<Score>() {
@Override
public int compare(Score a, Score b) {
return a.score < b.score? 1 : (a.score == b.score ? 0 : -1);
}
};
public Score(String scorer, int score) {
this.scorer = scorer;
this.score = score;
}
}

View File

@ -0,0 +1,124 @@
package com.me.pacman.state;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.me.pacman.FontRenderer;
import com.me.pacman.Score;
import com.me.pacman.PacDude;
public class HighScoreEntryState extends State {
private Texture background;
private Score score;
private int currLetter;
private char[] name;
private boolean flash;
private float elapsed;
public HighScoreEntryState(PacDude game, Score score) {
super(game);
this.score = score;
this.currLetter = 0;
this.flash = false;
this.elapsed = 0f;
this.name = score.scorer.toCharArray();
}
@Override
public void setup() {
this.background = game.assets.getHighScoresBackground();
Gdx.input.setInputProcessor(this.new Controller());
}
@Override
public void render() {
game.batch.draw(background, 0, 16);
game.fontRenderer.setColor(Color.YELLOW);
game.fontRenderer.draw(game.batch, "high scores", (8 * 8) + 4, 25 * 8);
game.fontRenderer.setColor(Color.CHARTREUSE);
game.fontRenderer.draw(game.batch, "score name", (8 * 8) + 4, 23 * 8);
game.fontRenderer.setColor(Color.BLUE);
game.fontRenderer.draw(game.batch, "" + score.score, (8 * 8) + 4, 18 * 9);
for (int i = 0; i < 3; i++) {
game.fontRenderer.draw(game.batch, String.valueOf((i == currLetter && flash)? '_' : name[i]), (16 + i) * 8 + 4, 18 * 9);
}
game.fontRenderer.setColor(Color.WHITE);
Score[] scores = game.highScores.getHighScores(9);
for (int i = 0; i < scores.length; i++) {
Score score = scores[i];
game.fontRenderer.draw(game.batch, String.format("%-8d%s", score.score, score.scorer), (8 * 8) + 4, (16 - i) * 9);
}
}
@Override
public void update(float dt) {
elapsed += dt;
if (elapsed >= 1/3f) {
elapsed = 0f;
flash = !flash;
}
}
@Override
public void dispose() {
Gdx.input.setInputProcessor(null);
}
private final class Controller extends InputAdapter {
@Override
public boolean keyDown(int keycode) {
switch(keycode) {
case Input.Keys.DOWN:
int nextIndex = FontRenderer.CHAR_TO_INDEX[name[currLetter]] - 1;
if (nextIndex < 0) {
nextIndex = 25;
}
flash = false;
name[currLetter] = FontRenderer.CHARS[nextIndex];
break;
case Input.Keys.UP:
nextIndex = FontRenderer.CHAR_TO_INDEX[name[currLetter]] + 1;
if (nextIndex > 25) {
nextIndex = 0;
}
flash = false;
name[currLetter] = FontRenderer.CHARS[nextIndex];
break;
case Input.Keys.RIGHT:
currLetter++;
if (currLetter > 2) {
currLetter = 0;
}
flash = true;
break;
case Input.Keys.LEFT:
currLetter--;
if (currLetter < 0) {
currLetter = 2;
}
flash = true;
break;
case Input.Keys.ENTER:
score.scorer = String.valueOf(name);
game.highScores.addScore(score);
game.setNextState(new HighScoresState(game));
break;
}
elapsed = 0f;
return super.keyDown(keycode);
}
}
}

View File

@ -0,0 +1,67 @@
package com.me.pacman.state;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.me.pacman.PacDude;
import com.me.pacman.Score;
public class HighScoresState extends State {
private Texture background;
public HighScoresState(PacDude game) {
super(game);
}
@Override
public void setup() {
this.background = game.assets.getHighScoresBackground();
Gdx.input.setInputProcessor(this.new Controller());
}
@Override
public void render() {
game.batch.draw(background, 0, 16);
game.fontRenderer.setColor(Color.YELLOW);
game.fontRenderer.draw(game.batch, "high scores", (8 * 8) + 4, 25 * 8);
game.fontRenderer.setColor(Color.CHARTREUSE);
game.fontRenderer.draw(game.batch, "score name", (8 * 8) + 4, 23 * 8);
game.fontRenderer.setColor(Color.WHITE);
Score[] scores = game.highScores.getHighScores(10);
for (int i = 0; i < scores.length; i++) {
Score score = scores[i];
game.fontRenderer.draw(game.batch, String.format("%-8d%s", score.score, score.scorer), (8 * 8) + 4, (17 - i) * 9);
}
}
@Override
public void dispose() {
Gdx.input.setInputProcessor(null);
}
@Override
public void update(float dt) {}
private final class Controller extends InputAdapter {
@Override
public boolean keyDown(int keycode) {
switch(keycode) {
case Input.Keys.ENTER:
case Input.Keys.ESCAPE:
game.setNextState(new MenuState(game));
break;
}
return super.keyDown(keycode);
}
}
}

View File

@ -11,7 +11,7 @@ import com.me.pacman.Sound;
public class MenuState extends LevelState { public class MenuState extends LevelState {
private Texture levelBackground; private Texture background;
private Texture logo; private Texture logo;
@ -29,7 +29,7 @@ public class MenuState extends LevelState {
@Override @Override
public void setup() { public void setup() {
levelBackground = game.assets.getMenuBackground(); background = game.assets.getMenuBackground();
logo = game.assets.getLogo(); logo = game.assets.getLogo();
logo.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear); logo.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
@ -48,7 +48,7 @@ public class MenuState extends LevelState {
@Override @Override
public void render() { public void render() {
game.batch.draw(levelBackground, 0, 16); game.batch.draw(background, 0, 16);
game.batch.draw(logo, 0, 140, 224, 120); game.batch.draw(logo, 0, 140, 224, 120);
@ -80,10 +80,10 @@ public class MenuState extends LevelState {
case Input.Keys.ENTER: case Input.Keys.ENTER:
switch (selectedOption) { switch (selectedOption) {
case NEW_GAME: case NEW_GAME:
game.setScreen(new PlayState(game)); game.setNextState(new PlayState(game));
break; break;
case HIGH_SCORES: case HIGH_SCORES:
// game.setScreen(new HighScores(game)); game.setNextState(new HighScoresState(game));
break; break;
} }
break; break;
@ -106,9 +106,9 @@ public class MenuState extends LevelState {
public boolean touchUp(int screenX, int screenY, int pointer, int button) { public boolean touchUp(int screenX, int screenY, int pointer, int button) {
Vector2 coords = game.viewport.unproject(new Vector2(screenX, screenY)); Vector2 coords = game.viewport.unproject(new Vector2(screenX, screenY));
if (selectedOption == 0 && NEW_GAME_BOX.contains(coords)) { if (selectedOption == 0 && NEW_GAME_BOX.contains(coords)) {
game.setScreen(new PlayState(game)); game.setNextState(new PlayState(game));
} else if (selectedOption == 1 && HIGH_SCORE_BOX.contains(coords)) { } else if (selectedOption == 1 && HIGH_SCORE_BOX.contains(coords)) {
selectedOption = -1; game.setNextState(new HighScoresState(game));
} else { } else {
selectedOption = -1; selectedOption = -1;
} }

View File

@ -10,7 +10,6 @@ public abstract class State extends ScreenAdapter {
public State(PacDude game) { public State(PacDude game) {
this.game = game; this.game = game;
this.setup();
} }
@Override @Override