Spencer Quin, Research In Motion
Artwork by Tudor Whiteley, Research In Motion

Rooster was a great project to work on. It was fun because we felt like we were really pushing the boundaries of the BlackBerry wireless device as far as it could go. One of the inspirations of the project was a desire to use the new game API that is part of the MIDP 2.0 specification.

It's kind of funny that I was so stuck on using the game API because, in the end, the only features that made it into Rooster were the image processing functionality and GameCanvas class. The problem was that Rooster only required a subset of the features that were available in the Sprite and Layer classes, so there were many calculations being made that weren't even necessary. The concepts and structure of the classes were sound, so I re-implemented the classes with only the necessary feature support.

Topics within this section include:

Java Games

Programming video games in Java has always been a touchy subject with game developers due to performance limitations imposed by the VM layer and sporadic garbage collection. One of the major challenges was to tame these issues as much as possible in order to keep the frame rate to a playable level.

The garbage collector for me is the biggest annoyance. It cannot be controlled in J2ME except if you want to trigger it manually. This may or may not save you from a random garbage collection in the heat of battle. There is nothing worse than a pause in the action caused by garbage collection.

The best way to limit the amount of garbage collection is to create all of the objects that will be used before the game play begins, and reuse them as necessary. This will increase the loading time, so you need to decide which is more important - long loading times or interrupted game play. If you are lucky, you will be able to invoke garbage collection at down times, like transitioning, between levels or between a user pause of the game.

Violating the rules!

Another problem with programming video games in Java is that the most efficient way of doing it flies in the face of good Java coding practices.

For instance, calling a method incurs an overhead so you want to make sure that your methods are large in order to reduce the number of method calls. Also, as handy as Vectors are, they will kill your performance. Other things you will want to do is avoid interfaces, unroll loops where possible, and do not add functionality to a class unless you intend to use it.

Size

Another consideration is the space issue. If you have downloaded Rooster, then you know this is a rather large download compared to most other BlackBerry applications. There are many techniques that can be used to reduce this.

One way is to use the vector drawing methods that are part of the Graphics object as much as possible. Unfortunately, these drawing methods will not give you the really fancy graphics that you see in Figure 1.


Figure 1: Rooster frames spliced into a single pngfile

To use these types of graphics, images need to be loaded. This is where the game will really start to grow in size. About 80% of the Rooster download is images. Splicing the images together like in Fig. 1 can help reduce the overall size since you will be removing the headers from the extra files. This was used quite a bit for the tile sets for each level and all of the animations.

The biggest space saver was using the right types of png and jpeg files. Adobe® Photoshop®, for example, exports 8-bit and 24-bit png images. While this is useful when creating quality work, it can prove problematic when deployed to a wireless handheld. Savings can be accomplished by reducing color depth, removing extras from the image such as meta data and profiles and using specialized encoding packages such as IrfanView or Windows® XP Paint. Also using 8 bit png files instead of 24 bit where possible is highly recommended. After applying some of these techniques, Rooster went from 260Kb to 150Kb. This was a very significant space savings. Aside from the technicalities, there were some other factors which really helped in the development of this title.

The following are some of the things that went right and wrong in the development of Rooster, presented in traditional postmortem style.

What Went Right

1. The team worked well together.

OK, so there were only two of us but between the two of us, we seemed to have the perfect balance of artistic and technical skills. Quite often when a technical issue arose, Tudor was able to come up with a good way to fake whatever effect that would be too expensive to do programmatically. I have worked on games on my own before and actually enjoy creating graphics as much as I enjoy programming, but I didn't mind handing over that task. Tudor's stuff was always as good as or better than anything I could do, since he was more experienced with using tricks to fool the eye into believing various effects. Also, he was able to suggest many things that I would never have thought of. The best example of this is the loading bar. If you are a programmer, I highly recommend hooking up with a good graphical artist.

2. Helped other departments test and debug their software.

This bonus was really unexpected but we were happy we could help. Because the MIDP 2.0 implementation was so new, there weren't many applications available to test it at the time. Rooster used the new technology and pushed it hard. It was also much more fun to use for debugging than many of the other business applications that were available. The amount of help and support that people from around the company were offering was incredible! I would like to send a special thanks to Connor O'Rourke who answered a million questions about why the early IDE had issues and what's up with this and that in MIDP 2.0.

3. Choice of game.

Luckily, Rooster appeals to a wide and diverse group of gamers. We have even had comments from people who told us they typically do not like video games, but Rooster was different. For our next game we would like to do something a little more action packed just to keep it fresh and interesting. Hopefully it will also have the same appeal.

What Went Wrong

1. Too many ideas.

Usually this is a good thing but, in our case, I think we could have worked on this game forever and still not have been finished.

One feature that I wanted to implement and wasted about a month on, was trying to get the cars to change lanes and pass each other. Unfortunately, there was an optimization on the collision detection methods that could only be achieved if the cars did not change lanes.

Each lane has its own array of vehicles and at any given time the rooster is straddling at most two lanes. This means that only these two lanes need to be considered for collision detection. The arrays are actually circular queues and new cars are inserted at one end and taken off of the other. This guarantees that the cars are ordered. The car positions only need to be checked with the rooster position and only the closest two cars are checked in each of the lanes that the rooster is straddling. In order to have cars pass each other, it would be necessary to splice the car out of one array and into the other. The lanes also have variable speeds, so it would be necessary to check the new lane to see if the change would cause a collision. There was also the possibility that two cars would want to change lanes at the same time and cause a collision with each other. So a check would also need to be performed with all of the cars that were currently in the state of changing lanes. This doesn't sound like much work but I just wasn't ready to give up a few precious cycles for that feature although Tudor begged and pleaded till his voice went hoarse and he was blue in the face.

2. Lack of Global Score server.

The value of this feature was seriously underestimated. I believe that people, by nature, are very competitive and the mobile platform allows this nature to surface if you let it by creating a global score server. It was one of the most requested features at launch time. The main reason, and really the only reason, that it wasn't implemented was that I didn't want to hard code a URL into the code since this may hamper the game's longevity and portability. I also didn't want to use http to transmit the information and did not have enough time to create my own server with a custom protocol.

3. Trying to program on the bleeding edge.

Using the latest and greatest technology is fun and exciting largely because you are doing things that no one else has done or seen before. Unfortunately, it can also be extremely frustrating since you will spend at least some of your time trying to debug and/or configure the technology you are trying to use before you can even apply it.

Many of the lessons that have been learned throughout the years for video games in general are also applicable to the mobile platform. In some ways, I suspect that programming mobile games today is similar to what it must have been back in the mid 90's. The only difference it seems is that mobile technology is achieving new standards at a higher rate than its PC cousins. Mobile 3D is already being realized in the OpenGL ES and JSR 184 specifications and it has already found its way into a select number of mobile devices. Hopefully BlackBerry will be among them in the near future.

Please email your comments, suggestions and editorial submissions to mail