From 5c227e53d1b3a37e94defaaf9e3df93c379aa841 Mon Sep 17 00:00:00 2001 From: Matt Low Date: Thu, 16 Jan 2020 12:32:32 +0400 Subject: [PATCH] Render fonts ourselves with a font spritesheet. Ensures font looks original to classic pac-man --- android/assets/sprites/font.png | Bin 0 -> 862 bytes android/assets/sprites/font.xcf | Bin 0 -> 4897 bytes core/src/com/me/pacman/Assets.java | 20 ++------ core/src/com/me/pacman/FontRenderer.java | 48 ++++++++++++++++++++ core/src/com/me/pacman/PacDude.java | 4 +- core/src/com/me/pacman/state/MenuState.java | 29 ++++-------- core/src/com/me/pacman/state/PlayState.java | 22 +++++---- 7 files changed, 75 insertions(+), 48 deletions(-) create mode 100644 android/assets/sprites/font.png create mode 100644 android/assets/sprites/font.xcf create mode 100644 core/src/com/me/pacman/FontRenderer.java diff --git a/android/assets/sprites/font.png b/android/assets/sprites/font.png new file mode 100644 index 0000000000000000000000000000000000000000..318e50a364ce6ae201bbd3a3bc08d0e015adf2c6 GIT binary patch literal 862 zcmV-k1EKthP)EX>4Tx04R}tkv&MmP!xqvTcskE4i*t{$WWauii!v>T7@E12(?114kj=CgC-40 zii@M*T5#}ZvFhOBtgC~oAPD||I5|2gx=4xlC509-UUt6(RCh6+<=yvZ^(Z-$0X~6vmg$B?yg@v* zY3ZEzi6g8iDa7Z*BL-cN_>t?f%Ws?u4*Pj##7L*+i6g{9p^fD>W<^6Ko+OScsz&+# zjLQn=EzWAW%9{7&FAU|hm1VBe8bkt%Sb_)vGO8${3=1*ZHBwBZ=sfP>A8`C4xny#c zz{s(H3RFmrAN&t~&(_ROjJrvpIMDfG+aE(fa2IIQZ2SAzwi_ov;2F5mTK-BMnEoWa z*3zO!KzJLtxNd3k9&ot>^grp6AvscjmOq~d-p}ZpvOw=G(7oo)t$B{q2Ov$eO5Okm zhrn=wve!M{-PJy~e|wtq`vK91a?MDX-*W%}00vM@R7C&)0RR90rP-g|00001bW%=J z06^y0W&i*H0b)x>L;#2d9Y_EG010qNS#tmY3ljhU3ljkVnw%H_000McNliru|u#HN%0g~CxYrdHe9Fd?QxSwI+uSZAw4QBMg$&$^ZJUY0 zVQvp>w4wO5puzJ!m9*&55H$SE8f<{fJFjwuXxnvT71%vxb&=q~04Qjic2k&(@2ZZ5 zin0K3&Neu^Z4{h4%=`e2#Zn+C`D;?t^P--Vx+~z%j5YvQgF3GDkNG*kq*P`3h)}4U o>X#E$2B^nBsm@2G0ssI207*qoM6N<$g8UzYKL7v# literal 0 HcmV?d00001 diff --git a/android/assets/sprites/font.xcf b/android/assets/sprites/font.xcf new file mode 100644 index 0000000000000000000000000000000000000000..734068b5cb93419017ff04f39e0424eba145a199 GIT binary patch literal 4897 zcmb7{OK($06vusiuN?@X1r@3;y0{H(6Bc>656U8hh^SPkU7%9bc4-pFSW4_DF(|Cs zFHotguG(+VuLlT1H2weP++&aP5Y*;)X3m`Ff9A{y-QLb_d9blnK3#6LYWl2IRM+^I zC=*SKSceewds&ph{y=o@&Y#8KkmgrJg$U6PllfJ#{?Yn!Z)0O&cW!gZyW5@F)tjZh zD@zhRTO}&~(CK%Fk7rkJeDyBUKle7@N%+T(j_1ixNj(&Jv#Vde#rQ8{h1u1wZ+x@# z#qwJ;e*GUB_a6_2gT-~O$pam?;AvIXSC+=eawy3s|2$dvbWIbeAv(V`=nofn`(4fB zZD(wXxc!vKC(LjEu3uG%2)<6ecD|ZxsLdwxkCQpYhCH8A&6`;e)ipoTOHvnQqE{lpG+M)ZUh&{JL`_j4LdSK}5gFfO?&Lhipjfc&vbHu} zrdWv$dYj$UW-1FG`)9=u|F}Fcr1-EumEg0ceR5CrJbveaZ5Hih**VEhVn<#^r}-yl zbY6?}k7Xmmkf$v7@S}0~Og+-YRr_LrgBGA|(mz9!(){MJe_0+ZVL8_C_9d}skNhGNO1-7DCc(A zFT`_O*r9gV$DX5PcJhcGsQOhSCgz#)w6~^SjrR6nZ|uwR&6OWEz{%_s*}7uLB9B-& zO?=zF$29qt875|XjEm=s?D-hi7(ZmW`cqY2mU|<{Oa8=#FRmYP*?t=Tk<$F#! zgVjknJ9A>VQtdZlPGG`0Q&vIoh3E^P-^Kh5U)I=e#Ql(6)S7tQ7q;p(#Ug7$L0>Xs z7bzz@8Kk&F#OM;lWhDmAoLe)SPBgIqMzM^gZ)Y*qPvg+GFeBeI63%im7w!`GAAiqc z?3dy%IhG>ucrRjPv10S8i28XiN|Hf*1e9H;2cugaq%|u~V)1p@7glt|Z z{#O5p_8L@XLB}0*{WNc?uQxRo;Yfe73rO*^@Je(3g!eVP=M@jWAPRyZ2+Anqy6K1v z`tX=LIge3~dGzP9wl)9GCIvaF{ASuyzL0oUNz5CmV0t(w((}7lZYWRmgCgzG+yfO&*($C zZqKsMqAld!AW@$#+$x8P;wI;!LN~<%^1v+V<|ugs2zdh)UC8CF zLdQ46#qg59IhQ>yw4BTY|L?N#0&>bf55POU_9?jv5kzPJUf4`Z#f=h0BtRs(iZ zu%{<1+VyDFUZZa!H>B)Hk#jrjslASDVTX5vedIiAM*M*usCqpS6LUR>l1HyzjrR6n zZ|uwRRU3;oz{%_sVO_StL(j7OaGLnGeUEAKEi+8a_GCVmQx?=-Wp9ihvaHoQWZO=( zP%Mrmap8*`iOcPb<3G|ltC*XWaT!56mFUUl8nUiDjx2(wGnPIfX#afi@z3F5-9;mo-;gWBsz6ANGz z%UJq$7GwQ14r1l()n1cGPUga0;{L0>2DMkos=db8LQs2+c&NROd|^}VRk4Mj_8Oze nLVN`HKRJeqp!TYyg2p1Kp+?ZuUM0**?KP;qMk%$|KzscUzNaF~ literal 0 HcmV?d00001 diff --git a/core/src/com/me/pacman/Assets.java b/core/src/com/me/pacman/Assets.java index bc6d492..ce9f425 100644 --- a/core/src/com/me/pacman/Assets.java +++ b/core/src/com/me/pacman/Assets.java @@ -19,6 +19,7 @@ public class Assets { private Texture levelWinBackground; private Texture menuBackground; + public TextureRegion[][] font; public TextureRegion[][] level; public TextureRegion[][] deathAnimation; public TextureRegion[][] ghosts; @@ -35,8 +36,6 @@ public class Assets { public Sound return_base; public Sound siren, siren_fast, siren_faster, siren_fastest; - private BitmapFont font; - public Assets() { this.manager = new AssetManager(); } @@ -47,6 +46,7 @@ public class Assets { manager.load("menu_background.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/death.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_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 manager.finishLoading(); - this.font = manager.get("fonts/joystix.ttf", BitmapFont.class); levelBackground = manager.get("level_background.png", Texture.class); levelWinBackground = manager.get("level_background_win.png", Texture.class); menuBackground = manager.get("menu_background.png", Texture.class); // 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); deathAnimation = TextureRegion.split(manager.get("sprites/death.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); } - public BitmapFont getFont() { - return font; - } - public void dispose() { manager.dispose(); } diff --git a/core/src/com/me/pacman/FontRenderer.java b/core/src/com/me/pacman/FontRenderer.java new file mode 100644 index 0000000..75f1e94 --- /dev/null +++ b/core/src/com/me/pacman/FontRenderer.java @@ -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; + } + } + +} diff --git a/core/src/com/me/pacman/PacDude.java b/core/src/com/me/pacman/PacDude.java index d066260..89bec36 100644 --- a/core/src/com/me/pacman/PacDude.java +++ b/core/src/com/me/pacman/PacDude.java @@ -23,6 +23,7 @@ public class PacDude extends Game { public Sound sound; public SpriteBatch batch; + public FontRenderer fontRenderer; public OrthographicCamera cam; public Viewport viewport; @@ -38,6 +39,7 @@ public class PacDude extends Game { sound = new Sound(this); batch = new SpriteBatch(); + fontRenderer = new FontRenderer(assets.font); Gdx.gl.glClearColor(0, 0, 0, 1); setScreen(new MenuState(this)); @@ -49,7 +51,7 @@ public class PacDude extends Game { batch.begin(); 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(); batch.end(); diff --git a/core/src/com/me/pacman/state/MenuState.java b/core/src/com/me/pacman/state/MenuState.java index 4be059d..2e42adb 100644 --- a/core/src/com/me/pacman/state/MenuState.java +++ b/core/src/com/me/pacman/state/MenuState.java @@ -1,12 +1,10 @@ package com.me.pacman.state; -import com.badlogic.gdx.Application; 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.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.math.Vector2; import com.me.pacman.PacDude; import com.me.pacman.Sound; @@ -15,7 +13,6 @@ public class MenuState extends LevelState { private Texture levelBackground; private Texture logo; - private BitmapFont font; 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 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 static final String[] options = { - "New Game", - "High Scores", - }; - public MenuState(PacDude game) { super(game); @@ -45,7 +32,6 @@ public class MenuState extends LevelState { levelBackground = game.assets.getMenuBackground(); logo = game.assets.getLogo(); logo.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear); - font = game.assets.getFont(); Gdx.input.setInputProcessor(this.new Controller()); game.sound.play(Sound.Effect.BEGINNING); @@ -65,11 +51,14 @@ public class MenuState extends LevelState { game.batch.draw(levelBackground, 0, 16); 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 @@ -81,11 +70,11 @@ public class MenuState extends LevelState { public boolean keyDown(int keycode) { switch (keycode) { case Input.Keys.UP: - selectedOption = selectedOption > 0 ? --selectedOption : options.length - 1; + selectedOption = selectedOption > 0 ? --selectedOption : 1; game.sound.play(Sound.Effect.CHOMP_1); break; case Input.Keys.DOWN: - selectedOption = selectedOption < options.length - 1 ? ++selectedOption : 0; + selectedOption = selectedOption < 1 ? ++selectedOption : 0; game.sound.play(Sound.Effect.CHOMP_2); break; case Input.Keys.ENTER: diff --git a/core/src/com/me/pacman/state/PlayState.java b/core/src/com/me/pacman/state/PlayState.java index d0b128a..9ea998d 100644 --- a/core/src/com/me/pacman/state/PlayState.java +++ b/core/src/com/me/pacman/state/PlayState.java @@ -39,7 +39,6 @@ public class PlayState extends LevelState { private Texture levelBackground, winBackground; private TextureRegion lifeSprite; - private BitmapFont font; public Random random; @@ -219,7 +218,6 @@ public class PlayState extends LevelState { public void setup() { levelBackground = game.assets.getLevelBackground(); winBackground = game.assets.getLevelWinBackground(); - font = game.assets.getFont(); lifeSprite = game.assets.pacman[2][1]; Gdx.input.setInputProcessor(new Controller()); @@ -258,12 +256,16 @@ public class PlayState extends LevelState { @Override public void render() { - game.assets.getFont().setColor(Color.WHITE); - game.assets.getFont().draw(game.batch, "" + score, 40, 279); + // Draw score + 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++) { game.batch.draw(lifeSprite, i * 16, 0); } + // Draw the level tiles level.render(LEVEL_OFFSET_X, LEVEL_OFFSET_Y); if (state == GameState.ROUND_WON) { @@ -295,19 +297,19 @@ public class PlayState extends LevelState { } if (paused) { - game.assets.getFont().setColor(Color.YELLOW); - game.assets.getFont().draw(game.batch, "paused", 90, 127); + game.fontRenderer.setColor(Color.YELLOW); + game.fontRenderer.draw(game.batch, "paused", 11 * 8, 15 * 8); } else { switch (state) { case PRE_NEW_GAME: case NEW_ROUND_WAIT: case START_ROUND_WAIT: - game.assets.getFont().setColor(Color.YELLOW); - game.assets.getFont().draw(game.batch, "ready!", 92, 127); + game.fontRenderer.setColor(Color.YELLOW); + game.fontRenderer.draw(game.batch, "ready!", 11 * 8, 15 * 8); break; case GAME_OVER: - game.assets.getFont().setColor(Color.RED); - game.assets.getFont().draw(game.batch, "game over", 78, 127); + game.fontRenderer.setColor(Color.RED); + game.fontRenderer.draw(game.batch, "game over", (9 * 8) + 4, 15 * 8); break; } }