The Android Developer's Challenge 2 has begun. The judging application is available for download on the market. If you're not familiar, the ADC is a contest sponsored by Google in which developers submit apps and games for Android. Apps are initially judged by users for a first round. Later, Google judges will be responsible for 60% of the score. The top 3 apps for any given category get a cash prize. An early version of one of my games, Light Racer 3D, is in this contest. Good luck to everyone who entered and thanks to Google for running it!
Light Racer 3D is complete! So much happened in the past 3 days that it's very difficult to write about one thing. I had decided on about day 9 to try to get Light Racer 3D finished in time for the Android Developer's Contest 2. It was a very ambitious goal, especially because that game was only partially working with about 25% of its total content just a day before. For 6 days I slept only about 4 hours per night and only took breaks when I absolutely had to. The hard work paid off because on Monday, Aug 31, we finished the game, submitted a trial version to the ADC and put the full version online on the Android market. I'm happy with how the game turned out, despite our lack of real artistic capability. While there are still a few bugs which will be fixed in a future version, the overall feel is good and the game is really fun.
Turning 90 degreees in an instant is hard on human eyes. After the game was working, I decided that the camera needs to be active and quick but also needs to be limited to a certain amount of movement. I added 4 camera modes to the world renderer: Above, Behind player, Beside player and Spinning. I then added the same code that I use to control player movement to the camera. Now, for every frame rendered, the camera checks where it is supposed to be, then tries to move there at the rate that I defined. I also really liked the way that the original F-Zero for SNES did the overhead view and zoom down to behind the player, so I added a similar sort of effect to the level intros. Besides camera work, there was a lot of modeling and texturing happening. None of us are very good at 3D modelling but by the end of the 2 days, we had already learned several tricks. All it takes is an ADC2 deadline to make you learn fast!
Light Racer 3D is an exciting project because every day of development adds substantial improvements to the game. The last 2 days have been no exception. Make sure to watch the video at the end of this post. It shows how totally playable the game is. If I were to stop right now, the game would be at least as good as a 3D counterpart to the original Light Racer. As it stands right now, I've got a list of about 20 things I'd like to do for this game to take it from cool to amazing. Because of memory allocation sensitivity on Android, I had to employ a few tricks to deal with the dynamic geometry of the trails. I also ran into a problem getting the explosions properly billboarded.
Days 5-7 have brought on a dramatic difference to the new game. It went from being a test bed for 3D objects and experimentation to an actual working scene. I laughed out loud when I first finished the merge of the 2D game engine with the new 3D rendering system because the problems were so bad but I was still able to see the racers and control them. It didn't take me much over an hour to fix up the issues and move the camera behind the player for that 3rd person following view. There are no trails, explosions or text yet but this will give you an idea of what the game will look like.
Every 3D game has a process defined for creating models, texturing and importing into the game. In these two days, I've come up with a process that works for Light Racer 3D and all of the games we will be developing in the future. This process will be a little different from project to project, depending on the requirements of the game and which tools you are using to create your art. I wanted to use Maya but was most familiar with 3D Studio Max so I went forward with it for Light Racer 3D.
I feel good about the game engine that I've developed while working on Light Racer. The only big thing that will be different about Light Racer 3D is that instead of drawing 2D sprites, each object will need to be rendered as 3D. To me, this sounds very simple. I plan on modeling everything in the game in 3D Studio Max, developing custom bits of rendering code then merging the 3D world renderer with the existing code base and tweaking to perfection. I'm confident that this will work, yet I'm pretty bad with 3DS, I've never developed anything in OpenGL, much less ES, and I have no existing tools to help me on my way. There has been a lot of reading and experimenting done, but at the end of the day, I have a working scene and a working OBJ file importer that maps textures correctly.
The initial update (2.0.0) of Light Racer was very shakey. I'm not entirely surprised, though. When I put out a game or a new app, I like to watch for feedback or signs of acceptance over the first few days. With this update, I got a lot of negative feedback about how the update ruined the original game. I was confused by that because I specifically put in the time trial mode to try to follow up the original version. I had underestimated how much many people enjoyed the simplicity of Light Racer 1. The first update addressed that issue by adding in classic modes and response to the update has significantly improved.
The last 4 days of work were some of the most intense. Finishing up a project always is. The majority of the work was completing all of the little things like music, sounds, preferences, menu options, layout and UI tweaks and vibration. What's really interesting about the last few days is how some of the most critical bugs tend to pop up right then. For instance, when we added a how-to-play dialog to the game just today (on the release day), it brought up a massive bug where the user couldn't input any control at all. I figured out why that was happening but am still having a few problems with that now and then. Perhaps someone could explain why a thread waiting on a synchronized block gets stuck waiting even though the mutex is bring locked and freed by another thread many times over? Even with that, we managed to get everything together and get the game onto the market!
The past several days of work have been focused on two things: Achievements and Leaderboards. We implemented an AchievementsCalculator that was called after every round and each multiplayer match. The achievements themselves are simply stored as a set of SharedPreferences. I decided to go that route because of how much simpler the implementation is than using an SQLLite Provider. I used a Provider to do the stats on Wuzzle and I believe it's simply overkill for storing 15 booleans. The leaderboard was a little more complex. Fortunately I had written most of the code once before when doing the Online Multiplayer code for Wuzzle so it was a matter of copy, paste and modify. The client uses REST/JSON to communicate with the leaderboard server which is Ruby on Rails deployed using Phusion Passenger on Apache.