This is the second article in a series that takes the final RPG code from the “How to Make an RPG” project and adds a little more polish to one element.
The Cave Quest demo in the book uses a lot of true type text. True type text works well for modern games but in a relatively low-resolution JRPG, bitmap text is better. Bitmap text can be aligned perfectly to the pixel grid so the text is sharp. If the true-type text happens to render in a way that’s not pixel-aligned then it’s very easy for it to appear blurry.
Here you can see a blown-up in game number; horribly blurry!
Why? Because the true type font is a vector image that’s been scaled down to the the pixel grid and it doesn’t nicely align to the pixels. The width of the font, instead of being 8 pixels might something like 6.7984582, it’s never going to fit nicely without getting a bit blurred.
Each piece of polish should take less than a day; that’s why I’m only changing the numbers to bitmap fonts.
Bitmap Font Engine
Dinodeck, the underlying C++ engine, handles fonts and drawing but it doesn’t support bitmap fonts natively. Therefore we’ll write the bitmap font code in Lua! In fact there’s already a project over here that can draw monospace, bitmapped fonts - which is fine for our number needs.
Current Number Fonts
Numbers are used all over the place.
- In-game Menu
- Time
- Gold
- Party Summary Panels
- Inventory Menu
- Status Screen
- Stats
- Party Member Summary Panel
- Level Summary Panel
- Shop
- Shop Prices
- Party Gold
- Equip and inventory counts
- Combat
- HP/MP Displays
- Jumping Number Effects (heal, damage etc)
- Combat Summary Screen
- XP
- Level
- Loot Screen
- Item Counts
- Gold Found
- Party Gold
All these places need updating in the code. Here’s how the screens look at the moment:
Note: The player actions text is at the wrong scale. I’ll fix that too while I’m in the code.
Here’s a screen I’m not going to change:
In this screenshot the number text is inline with dialog text so it’s tricky to change.
Sourcing a Replacement Font
Here’s the texture for the replacement font. You’re free to use this as I made it! The one shown below has been blown up 2x (download the original here).
Code Changes
For this article I’ll only go through a single example where I update the existing code to use a bitmap font.
Add the Bitmap Font Rendering Code
Each font is composed of two pieces; the texture and a lua definition describing the position of the glyphs in the texture. For the numbers I’ve added two files in the following locations:
/art/font/number_font.png
/code/font/NumberFontDef.lua
Then there’s the font rendering code that I’ve added in the main code directory.
/code/BitmapText.lua
The interface for using a bitmap font is the same as Dinodeck’s code for using true type fonts.
In main.lua file I create a global gNumberFont
to draw the number text in the game. When I come to add more fonts, I’ll move the number font out of global scope to somewhere more sensible.
LoadLibrary('Asset')
Asset.Run('Dependencies.lua')
gRenderer = Renderer.Create()
gNumberFont = BitmapText:Create(NumberFontDef)
That’s it for setup.
Using a Bitmap Font for the Gold Count
Now to demonstrate the process: I’ll update the number for the Gold count on the in-game menu. The gold value is rendered out in a state called FrontMenuState
. Here’s the relevant function:
function FrontMenuState:Render(renderer)
-- Lots of code omitted
local goldX = self.mLayout:MidX("gold") - 22
local goldY = self.mLayout:MidY("gold") + 22
renderer:ScaleText(self.mParent.mLabelSize, self.mParent.mLabelSize)
renderer:AlignText("right", "top")
renderer:DrawText2d(goldX, goldY, "GP:")
renderer:DrawText2d(goldX, goldY - 25, "TIME:")
renderer:AlignText("left", "top")
renderer:DrawText2d(goldX + 10, goldY, gWorld:GoldAsString())
In this snippet note that the the gold value comes from gWorld:GoldAsString()
and it’s being rendered using renderer:DrawText2d
, also note that the alignment is set to top
and left
. Here’s the modified function:
function FrontMenuState:Render(renderer)
-- Lots of code omitted
local goldX = self.mLayout:MidX("gold") - 22
local goldY = self.mLayout:MidY("gold") + 22
renderer:ScaleText(self.mParent.mLabelSize, self.mParent.mLabelSize)
renderer:AlignText("right", "top")
renderer:DrawText2d(goldX, goldY, "GP:")
renderer:DrawText2d(goldX, goldY - 25, "TIME:")
renderer:AlignText("left", "top")
-- New Lines:
gNumberFont:AlignText("left", "top")
gNumberFont:DrawText2d(renderer, math.floor(goldX + 10), math.floor(goldY), gWorld:GoldAsString())
Here you can see the difference:
The box on the top has the gold rendered very clearly and crisply while the one below is blurred. That’s the power of using bitmap fonts when working at low resolutions.
The Final Look
Here’s how some of the game screens look with the number changes. This was mostly swapping out the render calls to use the BitmapFont
code and a little realignment in places.
Obviously a further improvement would be to replace all remaining text with bitmap fonts and that’s definitely on the polish list.
Source
There’s a github with an updated project here.
Enjoyed this article? Share or link to it, to support the site and help fellow developers.