Render fonts ourselves with a font spritesheet.

Ensures font looks original to classic pac-man
This commit is contained in:
Matt Low 2020-01-16 12:32:32 +04:00
parent e4e0d0c1b0
commit 5c227e53d1
7 changed files with 75 additions and 48 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

View File

@ -19,6 +19,7 @@ public class Assets {
private Texture levelWinBackground; private Texture levelWinBackground;
private Texture menuBackground; private Texture menuBackground;
public TextureRegion[][] font;
public TextureRegion[][] level; public TextureRegion[][] level;
public TextureRegion[][] deathAnimation; public TextureRegion[][] deathAnimation;
public TextureRegion[][] ghosts; public TextureRegion[][] ghosts;
@ -35,8 +36,6 @@ public class Assets {
public Sound return_base; public Sound return_base;
public Sound siren, siren_fast, siren_faster, siren_fastest; public Sound siren, siren_fast, siren_faster, siren_fastest;
private BitmapFont font;
public Assets() { public Assets() {
this.manager = new AssetManager(); this.manager = new AssetManager();
} }
@ -47,6 +46,7 @@ public class Assets {
manager.load("menu_background.png", Texture.class); manager.load("menu_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/level.png", Texture.class); manager.load("sprites/level.png", Texture.class);
manager.load("sprites/death.png", Texture.class); manager.load("sprites/death.png", Texture.class);
manager.load("sprites/ghosts.png", Texture.class); manager.load("sprites/ghosts.png", Texture.class);
@ -69,25 +69,15 @@ public class Assets {
manager.load("sounds/siren_faster.wav", Sound.class); manager.load("sounds/siren_faster.wav", Sound.class);
manager.load("sounds/siren_fastest.wav", Sound.class); manager.load("sounds/siren_fastest.wav", Sound.class);
// Yayyy! all of this to load a font
FileHandleResolver resolver = new InternalFileHandleResolver();
manager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
manager.setLoader(BitmapFont.class, ".ttf", new FreetypeFontLoader(resolver));
FreetypeFontLoader.FreeTypeFontLoaderParameter font = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
font.fontFileName = "fonts/joystix.ttf";
font.fontParameters.size = 10;
font.fontParameters.mono = true;
manager.load("fonts/joystix.ttf", BitmapFont.class, font);
// finish loading assets from disk // finish loading assets from disk
manager.finishLoading(); manager.finishLoading();
this.font = manager.get("fonts/joystix.ttf", BitmapFont.class);
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);
// cache our texture regions // cache our texture regions
font = TextureRegion.split(manager.get("sprites/font.png", Texture.class), 8, 8);
level = TextureRegion.split(manager.get("sprites/level.png", Texture.class), 8, 8); level = TextureRegion.split(manager.get("sprites/level.png", Texture.class), 8, 8);
deathAnimation = TextureRegion.split(manager.get("sprites/death.png", Texture.class), 16, 16); deathAnimation = TextureRegion.split(manager.get("sprites/death.png", Texture.class), 16, 16);
ghosts = TextureRegion.split(manager.get("sprites/ghosts.png", Texture.class), 16, 16); ghosts = TextureRegion.split(manager.get("sprites/ghosts.png", Texture.class), 16, 16);
@ -128,10 +118,6 @@ public class Assets {
return manager.get("logo.png", Texture.class); return manager.get("logo.png", Texture.class);
} }
public BitmapFont getFont() {
return font;
}
public void dispose() { public void dispose() {
manager.dispose(); manager.dispose();
} }

View File

@ -0,0 +1,48 @@
package com.me.pacman;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
public class FontRenderer {
private static final char[] CHARS = "abcdefghijklmnopqrstuvwxyz0123456789!?()[]<>$&*:#^~-_/\\".toCharArray();
private static final int[] CHAR_TO_INDEX = new int[256];
private Color color = Color.WHITE;
private TextureRegion[][] sprites;
public FontRenderer(TextureRegion[][] sprites) {
this.sprites = sprites;
}
public void setColor(Color color) {
this.color = color;
}
public void draw(SpriteBatch batch, String str, int x, int y) {
float oldColor = batch.getPackedColor();
batch.setColor(color);
for (char c : str.toCharArray()) {
if (Character.isWhitespace(c)) {
x += 8;
continue;
}
int i = CHAR_TO_INDEX[c];
TextureRegion region = sprites[i / 8][i % 8];
batch.draw(region, x, y);
x += 8;
}
batch.setPackedColor(oldColor);
}
static {
for (int i = 0; i < CHARS.length; i++) {
CHAR_TO_INDEX[CHARS[i]] = i;
}
}
}

View File

@ -23,6 +23,7 @@ public class PacDude extends Game {
public Sound sound; public Sound sound;
public SpriteBatch batch; public SpriteBatch batch;
public FontRenderer fontRenderer;
public OrthographicCamera cam; public OrthographicCamera cam;
public Viewport viewport; public Viewport viewport;
@ -38,6 +39,7 @@ public class PacDude extends Game {
sound = new Sound(this); sound = new Sound(this);
batch = new SpriteBatch(); batch = new SpriteBatch();
fontRenderer = new FontRenderer(assets.font);
Gdx.gl.glClearColor(0, 0, 0, 1); Gdx.gl.glClearColor(0, 0, 0, 1);
setScreen(new MenuState(this)); setScreen(new MenuState(this));
@ -49,7 +51,7 @@ public class PacDude extends Game {
batch.begin(); batch.begin();
if (DEBUG) { if (DEBUG) {
assets.getFont().draw(batch, "FPS: " + Gdx.graphics.getFramesPerSecond(), 152, 287); fontRenderer.draw(batch, "fps:" + Gdx.graphics.getFramesPerSecond(), 19 * 8, 34 * 8);
} }
super.render(); super.render();
batch.end(); batch.end();

View File

@ -1,12 +1,10 @@
package com.me.pacman.state; package com.me.pacman.state;
import com.badlogic.gdx.Application;
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.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.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.me.pacman.PacDude; import com.me.pacman.PacDude;
import com.me.pacman.Sound; import com.me.pacman.Sound;
@ -15,7 +13,6 @@ public class MenuState extends LevelState {
private Texture levelBackground; private Texture levelBackground;
private Texture logo; private Texture logo;
private BitmapFont font;
public static final int NEW_GAME = 0; public static final int NEW_GAME = 0;
@ -24,17 +21,7 @@ public class MenuState extends LevelState {
private BoundingBox NEW_GAME_BOX = new BoundingBox(88, 66, 136, 84); private BoundingBox NEW_GAME_BOX = new BoundingBox(88, 66, 136, 84);
private BoundingBox HIGH_SCORE_BOX = new BoundingBox(88, 42, 136, 60); private BoundingBox HIGH_SCORE_BOX = new BoundingBox(88, 42, 136, 60);
private static final int MENU_PADDING = 24;
private static final int MENU_X = 84;
private static final int MENU_Y = 85;
private int selectedOption; private int selectedOption;
private static final String[] options = {
"New Game",
"High Scores",
};
public MenuState(PacDude game) { public MenuState(PacDude game) {
super(game); super(game);
@ -45,7 +32,6 @@ public class MenuState extends LevelState {
levelBackground = game.assets.getMenuBackground(); levelBackground = 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);
font = game.assets.getFont();
Gdx.input.setInputProcessor(this.new Controller()); Gdx.input.setInputProcessor(this.new Controller());
game.sound.play(Sound.Effect.BEGINNING); game.sound.play(Sound.Effect.BEGINNING);
@ -65,11 +51,14 @@ public class MenuState extends LevelState {
game.batch.draw(levelBackground, 0, 16); game.batch.draw(levelBackground, 0, 16);
game.batch.draw(logo, 0, 140, 224, 120); game.batch.draw(logo, 0, 140, 224, 120);
for (int i = 0; i < options.length; i++) {
font.setColor(i == selectedOption? Color.BLUE : Color.WHITE);
font.draw(game.batch, options[i], MENU_X, MENU_Y - (i * MENU_PADDING), 56, 1, true); game.fontRenderer.setColor(selectedOption == 0 ? Color.BLUE : Color.WHITE);
} game.fontRenderer.draw(game.batch, "new", (12 * 8) + 4, (9 * 8) + 4);
game.fontRenderer.draw(game.batch, "game", 12 * 8, (8 * 8) + 4);
game.fontRenderer.setColor(selectedOption == 1 ? Color.BLUE : Color.WHITE);
game.fontRenderer.draw(game.batch, "high", (12 * 8), (6 * 8) + 4);
game.fontRenderer.draw(game.batch, "scores", (11 * 8), (5 * 8) + 4);
} }
@Override @Override
@ -81,11 +70,11 @@ public class MenuState extends LevelState {
public boolean keyDown(int keycode) { public boolean keyDown(int keycode) {
switch (keycode) { switch (keycode) {
case Input.Keys.UP: case Input.Keys.UP:
selectedOption = selectedOption > 0 ? --selectedOption : options.length - 1; selectedOption = selectedOption > 0 ? --selectedOption : 1;
game.sound.play(Sound.Effect.CHOMP_1); game.sound.play(Sound.Effect.CHOMP_1);
break; break;
case Input.Keys.DOWN: case Input.Keys.DOWN:
selectedOption = selectedOption < options.length - 1 ? ++selectedOption : 0; selectedOption = selectedOption < 1 ? ++selectedOption : 0;
game.sound.play(Sound.Effect.CHOMP_2); game.sound.play(Sound.Effect.CHOMP_2);
break; break;
case Input.Keys.ENTER: case Input.Keys.ENTER:

View File

@ -39,7 +39,6 @@ public class PlayState extends LevelState {
private Texture levelBackground, winBackground; private Texture levelBackground, winBackground;
private TextureRegion lifeSprite; private TextureRegion lifeSprite;
private BitmapFont font;
public Random random; public Random random;
@ -219,7 +218,6 @@ public class PlayState extends LevelState {
public void setup() { public void setup() {
levelBackground = game.assets.getLevelBackground(); levelBackground = game.assets.getLevelBackground();
winBackground = game.assets.getLevelWinBackground(); winBackground = game.assets.getLevelWinBackground();
font = game.assets.getFont();
lifeSprite = game.assets.pacman[2][1]; lifeSprite = game.assets.pacman[2][1];
Gdx.input.setInputProcessor(new Controller()); Gdx.input.setInputProcessor(new Controller());
@ -258,12 +256,16 @@ public class PlayState extends LevelState {
@Override @Override
public void render() { public void render() {
game.assets.getFont().setColor(Color.WHITE); // Draw score
game.assets.getFont().draw(game.batch, "" + score, 40, 279); game.fontRenderer.setColor(Color.WHITE);
game.fontRenderer.draw(game.batch, "" + score, 5 * 8, 34 * 8);
// Draw remaining lives
for (int i = 0; i < lives; i++) { for (int i = 0; i < lives; i++) {
game.batch.draw(lifeSprite, i * 16, 0); game.batch.draw(lifeSprite, i * 16, 0);
} }
// Draw the level tiles
level.render(LEVEL_OFFSET_X, LEVEL_OFFSET_Y); level.render(LEVEL_OFFSET_X, LEVEL_OFFSET_Y);
if (state == GameState.ROUND_WON) { if (state == GameState.ROUND_WON) {
@ -295,19 +297,19 @@ public class PlayState extends LevelState {
} }
if (paused) { if (paused) {
game.assets.getFont().setColor(Color.YELLOW); game.fontRenderer.setColor(Color.YELLOW);
game.assets.getFont().draw(game.batch, "paused", 90, 127); game.fontRenderer.draw(game.batch, "paused", 11 * 8, 15 * 8);
} else { } else {
switch (state) { switch (state) {
case PRE_NEW_GAME: case PRE_NEW_GAME:
case NEW_ROUND_WAIT: case NEW_ROUND_WAIT:
case START_ROUND_WAIT: case START_ROUND_WAIT:
game.assets.getFont().setColor(Color.YELLOW); game.fontRenderer.setColor(Color.YELLOW);
game.assets.getFont().draw(game.batch, "ready!", 92, 127); game.fontRenderer.draw(game.batch, "ready!", 11 * 8, 15 * 8);
break; break;
case GAME_OVER: case GAME_OVER:
game.assets.getFont().setColor(Color.RED); game.fontRenderer.setColor(Color.RED);
game.assets.getFont().draw(game.batch, "game over", 78, 127); game.fontRenderer.draw(game.batch, "game over", (9 * 8) + 4, 15 * 8);
break; break;
} }
} }