Choppiness in game play can be an absolute make or break deal for the success of any game. I never thought that the first Light Racer would get downloaded and played as many times as it has. If I had realized that then, I probably would have invested a few more days smoothing it out. All of that is water under the bridge now though because the last 2 days of work have brought Light Racer 2 up between 45 and 60 frames per second on the G1 and no stutter in game from garbage collection or resource management. I covered all of the issues I faced and provided some solutions. This will probably apply to many other games as well.
I had previously written a little app that I was going to call "Fingerpaint" but I never released it because there already seemed to be other apps on the market that did that better. I did get it working and I'm glad I did because it made me very familiar with how to process sliding touches. I copied the code out of that sketch app and modified it to process touches for Light Racer. Now the user can touch anywhere on the screen and swipe in the direction they'd like the racer to go.
Wow, so much has happened in the past 6 days. My tasks were to finalize how items and NPCs spawned and finish Easy, Medium and Hard AI. Most of the time was spent optimizing algorithms, adding collision checks, changing little bits of design here and there and testing. Testing testing testing. This is the stage where it really gets tiring to play your own game. It just starts to lose some luster after the 100th time you've tried the same level against an Easy CPU. That's ok though because I pushed through and 6 days later, I've got most of the core game done.
While doing performance testing of Light Racer 2, I had to figure out how to do the fastest common operations. One problem I found was that I was drawing a static background in a 32 bit color mode with transparency when it was much faster to draw it in 16 bit with none. Another thing I wanted to check for was to see what was faster for finding half of a number: Division by two or multiplication by point-five? This matters because I do a whole lot of that in the game to place graphics and find mid-points for various physics and AI stuff. I wasn't sure which would be faster because the ARM processor in a G1 has neither a hardware divider nor a floating point unit. I wrote this little utility to tell me how many frames per second I can get with various operations. Also - Divide by two is at least twice as fast.
My project plan called for the completion of the levels in the game and then on to do more work on the AI, but I decided instead to take a couple of days to finish up some odds and ends that I have been spending too much time thinking about, which came to be graphics improvements, zooming, player indicators and scoring. These two days have done more for the overall feel and polish of the game than anything I have done so far. The zooming got me to thinking about different ways to make 2D games interesting. I still have 6-8 weeks left of development to get Light Racer 2 and Light Racer 3D done but I'm already thinking about how I can use what I've learned on this project in my next game. Anyway, here is what was done on days 23 and 24.
The final stage of the game is called "Portals." When a player goes into a portal, he comes out facing a different direction on the other side of the map. It's simple but also risky. I randomized where the player comes out of so there's no way to guarantee safe exit when there are trails blocking parts of the other portal. Overall this map feature was fairly simple to implement and it makes for yet another interesting dynamic to the game. I'm very happy to be totally finished with map features because now I can go about assembling and tweaking everything to make the game really feel complete.
Implementing the laser sweep was one of the most fun parts of the development so far. I wanted the laser to feel like it was controlled by a conscious being and I believe I achieved that effect. The turret is menacing; it locks on to a player and tracks them before charging up and firing a sweeping blast of laser. I was originally planning on having the laser also decimate any trails it touched but after playing with it for a while, I decided that it was plenty effective just as a player killer. The art really worked out well for it too. I'll include what I drew in photoshop so you can see what I did to make it turn out nicely in the game.
Sometimes finishing the detail work can be the hardest part of completing any project. Games are certainly no exception! My project plan called for me to move forward but instead I decided to take a day to improve sound and finish collisions for everything done to-date. This means that after day 18, there are new sounds in for the decimator, power lines and item pick-ups. I process the sounds myself using audacity but usually the base sounds come from free sound banks online.
After getting a decent graphic in for the Decimator, I began working on design changes that would allow Light Racer to have 10 unique levels. I implemented a LevelBuilder class that is responsible for configuring the World for a given level number. I tried to take into account the idea of the skirmish game later for single and multi-player modes in this design. I created the base MapObject class. A MapObject is any obstacle or interactive GameObject that's considered part of the "level." My first MapObject is the PowerLine, which is an object spanning a distance either vertical or horizontal that periodically arcs tesla-like lightning across the coils. The important thing for now is that per level, different numbers of AI players can be placed in different starting locations facing different directions, MapObjects can created and placed anywhere and initial speeds can be set on the players.
NPC stands for Non-Player Character. It's anything in the game that acts upon the world but is never directly controller by a player. Light Racer 2.0's only NPC is the Decimator. The Decimator is a menacing machine that flies in when the round is taking too long and starts smashing things up. Since it's the first object that can travel any direction, the physics math was a little bit different than for all of the existing code. Also, it needed some unique collision detection because it hits an area instead of hitting a straight line like the racers do. While the Decimator is an ugly purple pentagon at the end of the day, I'm happy with how it feels within the game. I think that with a little graphics and sound TLC, it'll be an excellent addition.