Skip to main content

Word Up

Dodging bullets is fun, but we need to start communicating information to the player. One of the most basic ways to do this is with text. In this post I'll add old school mono-spaced pixel font support to the game, and use that to show some simple placeholder info.



It all starts with a font sheet:


The font sheet is just a normal PNG image with transparency, but it has some special size properties. You'll notice that each character is 16x16 pixels in size, and that there are 16 characters per line and 8 rows. That gives us a total of 128 characters - enough to cover the entire ASCII character set. There are a few characters missing from the image, but most of these are control codes or special characters that we are not worried about. If you want, you could place your own special characters there instead.

Once the font image is loaded, it's easy to use drawImage() to cut individual characters out and draw them to the canvas. Step through a text string one character at a time, printing each one to the screen while advancing a virtual cursor and you're done. All of this functionality is wrapped up in a simple print() function that takes an x/y position and a string. There's a little bit more to do though - firstly I pick up and handle newline characters in the string, and secondly I added the ability to align blocks of text.

Alignment

Text alignment can be separated into two types: horizontal and vertical. Horizontal alignment can be either left, middle or right. For left alignment all lines of text start at the supplied x position, for right alignment all lines of text end at the supplied x position and for middle all lines are centered on the x position. Vertical alignment is similar, with top, middle and bottom options.

To make alignment work, I need to know the length of each line and the length of the longest line (for horizontal alignment) and the total height of the text (for vertical alignment). This is pretty easy to figure out from the text string itself, especially since I am using fixed width characters. I wrote a function in the Font class called getExtents() which gets the extents of a piece of text and returns them as an object - we'll see the code for that a little later on.

Enumerations

The other interesting thing you might spot in the Font class is the use of enumerated types. Enumerated types are a way of defining our own special, reserved names instead of using magic numbers in the code. So I could say that the alignment types left/middle/right have a values of 0/1/2, pass one of those values into the print function to specify which type of alignment I want, and then check for these values in the print code and preform the requested type of alignment. I would have to remember those numbers and always use the right ones, and if I ever changed them I would need to go back and find and change all references in the code. It would be better if I could just use the words LEFT/MIDDLE/RIGHT instead. These would make much more sense to me as a programmer, which makes the code easier to read and maintain - and that's exactly what enumerated types are for. Another key thing about an enumerated type is that they cannot be changed - imagine the chaos if I accidentally re-assigned the value of one of the types at runtime? The final trick up the sleeve of enumerated types is that, in a language like C++, we can catch at compile time if the programmer accidentally misspells a value when trying to use it.

Unfortunately, JavaScript doesn't support enumerated types but they can be easily added with some code. I add a Enum class that stores the values inside an object and the freezes them so that they cannot be changed. Another function, disallowUndefinedProperties(), is used to wrap the enum class so that it throws an error if the programmer attempts to read a value that wasn't defined. Finally, because there's a lot to remember here, there's a helper function called makeEnum() that takes an object and turns it into an enumerated type object in one easy step:


You'll see this helper function in use in the font class later on. In the meantime, there's some more info on emulating enumerated types in JavaScript here - which is where I got the implementation idea from.

The Font Class

Here's the whole font code. You can see the enumerated types for horizontal and vertical alignment at the top, and then the Font class itself underneath.


There are a couple of tricks to look out for in this code. Firstly, the constructor, on line 16, takes as an argument the number of characters wide (charsWide) the font image is. Because we know that there are 128 characters in total, we can use this number along with the width and height of the source image to figure out the size of each character (charWidth and charHeight). The constructor also takes x and y padding values (xSpacing and ySpacing), and when characters are printed I insert this many extra pixels between each character. Without this padding the characters tend to bunch up a bit too close to each other and become hard to read. Finally, look at how the alignment values (xAlign and yAlign) are used to alter the start positions of each line of text, based on the values returned from the getExtents() function.

Wrapping Up

Quite a long post this time. I added font support to the game and then used that to show some basic text on the screen. I also added some utility functions for creating enumerated types.

As always, the code is available here and the playable online version is here.

Next..

Well, it seems that the text doesn't always display - you might need to refresh the page before it shows up. I believe this is due to a small delay in loading the image resources. The first time the page is loaded the font image takes a little while to decode, and I try to generate the font before it's ready to be used. On subsequent page loads the resource is already cached so it's immediately ready to be turned into a font.

This is a defect that needs fixing, so I'll be doing some bug investigation and fixing that in the next post.

Comments

Popular posts from this blog

Set The Controls For The Heart Of The Sun

When we last met, I had just started work on a level editor. I'd got as far as adding the ability to select an object and move it around, and then I added an undo/redo system using the command pattern. That was a good start, but dragging items around the level is only fun for so long. What I really want to be doing is.. ..editing the properties of the bullet spawners! And I want to be doing this in realtime as the game plays so that I can immediately see what effect my changes have made to the gameplay of the level.

World In Motion

In the last post I touched on how easy it is to score in this game - you can just camp out on the score bullet spawner and watch the points rack up. I'm going to add a little delay to the score bullets so that they start out in a deactivated and uncollectable state, and then change to active and collectable after a short time - say, half a second. To make it clear what state they are in I'm going to add code to let me change the look of Objects and allow them to be animated.

The Long And Winding Road

I started this blog back in November of last year. My aim was to document the development of a Bullet Hell shoot-em-up, written in JavaScript. Here we are, six months later, and lots has happened. With 20 posts already written, I thought that now would be a good time to take stock of what I've already done, and to look to the future and see what's to come.