June 1GAM – Blue Ball Defender: Web Edition

For my June One Game a Month project and my first every HTML 5 game I’ve reused a little trick designed to make it easier to learn a new technology. My May project was a game called Blue Ball Defender implemented in Python/Pygame. Having made the decision to transition to HTML 5 I decided to simply reimplement Blue Ball Defender in the new language. There will be plenty of time to tackle exciting new projects once I’ve got to grips with the basics of HTML 5.

To make the transition even easier I completed the HTML 5 game development course on Udacity. I’m a big fan of online courses and have completed quite a few of them. Sadly, I was not particularly impressed by this one.

It appeared to be run by a group of Google developer outreach people, not teachers, which probably explains why there was very little teaching going on. It was more like an extremely detailed code walk through. It was useful for me as I was able to collect some useful looking bits of code but unless you have done a little game development before and have a pretty solid programming background I would not recommend it. One minute we’re learning how to display an image, the next we were talking about multi-layered map data.

If you’re looking for a course to get started making games check out Coursera’s interactive Python course. It offers a far smoother ramp up and you’ll build a series of increasingly complex playable games which is far more enjoyable than plugging away at the pieces of a single large project.

Back to Blue Ball Defender. The process of actually recreating my game in Javascript in Chrome was relatively painless. I find the syntax rather unintuitive but you get used to it. The inheritance, or lack thereof, is also a hassle.

Fortunately Blue Ball Defender is relatively simple and only uses a handful of resources. Dealing with images and sounds is a real pain in Javascript. You need to be conscious of whether or not the resource you need has loaded yet and be aware of the loading process. Compare that to a local application where you can pretty much just ignore the time it takes to load an image or sound file from the hard drive.

One significant side effect of the need to more carefully manage your resources is that I have removed the music. The download time for a 3MB mp3 just seemed to slow things down. Maybe it’s just my net connection. It’s probable that there is a smarter to way to deal with music but I’m unaware of it so, for the time being, there’s no music. I’ll figure it out for my next project.

After I had it up and running in Chrome I tried it out in Firefox. Urgh, the spacebar press to start the game isn’t registering. Once I resolved that the mouse clicks weren’t working correctly. Briefly, here is what I did to get it all working in both browsers.

It appears that the keypress codes for the two browsers are different so my on key press handler was not correctly identifying a spacebar press. I read a page about Javascript key events, switched from using the keypress event to the apparently more standard keydown and that resolved one of my problems.

The mouse click was more hairy. I was originally using plain old event.x and y in Chrome and that worked nicely. However, those variables didnt exist in Firefox. Other variables do but they report the mouse click location relative to the top of the window or some other unhelpful location. I needed the coordinates relative to the canvas top left.

What finally worked was a combination of this and this. There may be a simpler way but this appears to work and will do well enough.

Here is the final version. I’m sure that we can all agree that it’s hideous.

function onMouseClick(event) {
    if (gState == State.INGAME) {
        var mouseX;
        var mouseY;
        if ( event.offsetX == null ) { // Firefox
            //mouseX = event.layerX;
            //mouseY = event.layerY;
            if (event.pageX || event.pageY) { 
              mouseX = event.pageX;
              mouseY = event.pageY;
            else { 
              mouseX = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; 
              mouseY = event.clientY + document.body.scrollTop + document.documentElement.scrollTop; 
            mouseX -= gCanvas.offsetLeft;
            mouseY -= gCanvas.offsetTop;
        } else {                       // Other browsers
           mouseX = event.offsetX;
           mouseY = event.offsetY;

        gMissiles.push(new FriendlyMissile([mouseX, mouseY]));

Right now I’m quite negative about the whole experience. It’s certainly nice to be able to play in the browser and I suspect it will be far easier to attract players because of that but Javascript introduces new headaches without really offering much in return. It’s painful but necessary. Like a trip to the dentist.

Anyhow, enough of me banging on. Here it is.

Now I need to work out what I’m going next…