Scaling Bitmap Font Made With Font 2 PNG in Monkey X

This time a little tutorial on how to scale bitmap font made with Font 2 PNG in Monkey X.

The code uses DrawImageRect command to draw the font. The font.dat file has two 4 byte integers for each character. First is the starting position in the PNG-file in pixels, the second is the width of the character, in pixels. These are consecutively for each character.

The text is centered with the current scale. In order to get the text appear correctly, in drawString function also the width of the character must be multiplied with the scale.

As for the Font 2 PNG, the font is saved with black background color and in the code the blend mode is AdditiveBlend and the font looks smooth.

Here’s the code:

Import mojo
Import brl.filestream

Function Main()
	New MyApp

Class MyApp Extends App
	Const FONT_HEIGHT:Float = 37

	Field gfxBG:Image
	Global angle:Float	
	Global fontDat:Int[][]
	Global gfxFont:Image
	Global textX:Int, textY:Int
	Global textScale:Float
	Method OnCreate()

		gfxFont = LoadImage("font.png")
		Local File:=FileStream.Open("monkey://data/font.dat","r")

		fontDat = allocateArray(95,2)
		For Local i:Int = 0 To 95 - 1
			fontDat[i][0] = File.ReadInt()
			fontDat[i][1] = File.ReadInt()
		gfxBG = LoadImage("bg3.png")
		angle = 180
	Method OnUpdate()
		textScale = (2 - Cos(angle)) * 1.5
		angle = angle + 4
	Method OnRender()
		SetBlend AlphaBlend
		SetAlpha 1
		DrawImage gfxBG,0,0
		SetBlend AdditiveBlend
		drawString("Sample Text", (1024 - (stringWidth("Sample Text") * textScale)) / 2, (768 - (FONT_HEIGHT * textScale)) / 2, textScale)
	Function drawString(text:String, x:Float, y:Float,scale:Float)
		Local len = text.Length()
		Local chrs:Int[]
		chrs = text.ToChars()
		For Local i = 0 To len - 1
			'                            pos. in font.png          width in pixels in font.png
			DrawImageRect gfxFont, x, y, fontDat[chrs[i]-32][0], 0, fontDat[chrs[i]-32][1], FONT_HEIGHT,0,scale,scale,0
			x = x + fontDat[chrs[i]-32][1] * scale

	Function stringWidth:Int(text:String)
		Local len:Int = text.Length()
		Local chrs:Int[]
		Local length:Int = 0
		chrs = text.ToChars()
		For Local i:Int = 0 To len - 1
			length = length + fontDat[chrs[i]-32][1]
		Return length
	Function allocateArray:Int[][](i:Int, j:Int)
    	Local arr:Int[][] = New Int[i][]
    	For Local index = 0 Until i
    	    arr[index] = New Int[j]
    	Return arr		

End Class

You may use freely this code.

Below is a YouTube video of this tutorial: