Introduction
West Bank uses a really lovely double height font, but that means I can’t use the (very handy!) unicode font which I used in the Goldfish Game.
Instead, as the font images are extracted using Skoolkit, these can be
output to the screen in an almost similar way. The only difference being that
it’s no longer possible to use “text” process methods - as the output is now a
bunch of sprites instead (e.g. .setText()
). We can still store the references
in a similar way using this.textObjects
, and this helps with reprocessing the
“text” as and when it’s needed.
So, as before - the constructor is the same:
constructor() {
super();
// Storage for any text which might need altering (e.g. the score).
this.textObjects = {};
// Simply because I've made the assets use scale 4 in the disassembly.
this.gameScale = 4;
}
It’s only numbers we’re outputting, so preload these assets:
preload() {
// Preload the font assets.
for (let i = 0; i <= 9; i++) {
this.load.image(`char-${i}`, `/images/westbank/char-${i}.png`);
}
}
The printAt()
method can no longer use text functions, and each image needs
to be independently placed:
processChars(text) {
return text.split('').filter(char => char >= '0' && char <= '9');
}
printAt(text, x, y, colour = 0xFFFFFF) {
const sprites = [];
this.processChars(text).forEach((char, index) => {
const digitGroup = {
// The font outputs in two halves; the top part is a default white colour.
top: this.add.image(
8 * (x + index) * this.gameScale,
8 * y * this.gameScale,
`char-${char}`
).setOrigin(0, 0)
.setCrop(0, 0, 8 * this.gameScale, 8 * this.gameScale),
// But the bottom half can be any other (BRIGHT) colour.
bottom: this.add.image(
8 * (x + index) * this.gameScale,
8 * y * this.gameScale,
`char-${char}`
).setOrigin(0, 0)
.setCrop(0, 8 * this.gameScale, 8 * this.gameScale, 8 * this.gameScale)
.setTint(colour)
};
sprites.push(digitGroup);
});
return sprites;
}
And to alter the score text inside of the “sprite group”:
updateText(spriteGroup, text) {
this.processChars(text).forEach((char, index) => {
if (index < spriteGroup.length) {
spriteGroup[index].top.setTexture(`char-${char}`);
spriteGroup[index].top.setCrop(0, 0, 8 * this.gameScale, 8 * this.gameScale);
spriteGroup[index].bottom.setTexture(`char-${char}`);
spriteGroup[index].bottom.setCrop(0, 8 * this.gameScale, 8 * this.gameScale, 8 * this.gameScale);
}
});
}
And, to demonstrate it working, I’ve added these methods to “roll” the score
digits, choose different colour/ tint, and also reposition them every time they
go from 999999
->000000
.
placeScore() {
// Get random x and y coordinates.
const randomX = Phaser.Math.Between(0, 26);
const randomY = Phaser.Math.Between(0, 22);
this.textObjects['score'].forEach((sprite, index) => {
sprite.top.x = 8 * (randomX + index) * this.gameScale;
sprite.top.y = 8 * randomY * this.gameScale;
sprite.bottom.x = 8 * (randomX + index) * this.gameScale;
sprite.bottom.y = 8 * randomY * this.gameScale;
});
}
pickColour() {
const randomColour = Phaser.Math.Between(1, 7);
return [
0x000000,
0x0000FF,
0xFF0000,
0xFF00FF,
0x00FF00,
0x00FFFF,
0xFFFF00,
0xFFFFFF
][randomColour];
}
create() {
// Initialise the score.
this.data.set('score', 0);
// 32 less the length of the padded score.
const randomX = Phaser.Math.Between(0, 26);
// 24 less the (double) height of the digit.
const randomY = Phaser.Math.Between(0, 22);
// Stash a reference to the printed score item.
this.textObjects['score'] = this.printAt(
// Pad left with zeros to six digits.
Phaser.Utils.String.Pad(this.data.get('score'), 6, "0", 1),
// At a random screen position.
randomX, randomY,
// Pick a random colour.
this.pickColour()
);
// Add an event to increment the score for demo purposes.
this.time.addEvent({
delay: 500,
callback: this.incrementScore,
callbackScope: this,
loop: true
});
}
incrementScore() {
// Increment the score by one.
this.data.set('score', this.data.get('score') + 111111);
// Just for this demo, keep looping.
if (this.data.get('score') > 999999) {
this.data.set('score', 0);
this.placeScore();
}
// Update the printed score item.
this.updateText(
this.textObjects['score'],
Phaser.Utils.String.Pad(this.data.get('score'), 6, "0", 1)
);
}
And updated the updateText()
method to also choose a random colour for the
bottom half:
updateText(spriteGroup, text) {
const randomColour = this.pickColour();
this.processChars(text).forEach((char, index) => {
if (index < spriteGroup.length) {
spriteGroup[index].top.setTexture(`char-${char}`);
spriteGroup[index].top.setCrop(0, 0, 8 * this.gameScale, 8 * this.gameScale);
spriteGroup[index].bottom.setTexture(`char-${char}`);
spriteGroup[index].bottom.setCrop(0, 8 * this.gameScale, 8 * this.gameScale, 8 * this.gameScale);
spriteGroup[index].bottom.setTint(randomColour);
}
});
}