A couple of weeks ago I submitted a space sim to the udevgames competition (see my previous blog post). Ashima IV didn’t win any prizes, but that was hardy unanticipated, given that the game was barely to a playable state. Overall, I think the experience was very rewarding, and I hope a few of the lessons learned can be informative to others as well…
What went right:
– Choosing Python
I used to do all my development in C++, but over the last year I have made an almost complete transition to Python. Python is a wonderful little language, and well suited for small games. The flexibility of the language proved especially useful when implementing the entity system, as it is trivial to add data and methods to existing objects, on the fly.
The one grey area is performance: for a highly demanding application such as a game, python’s interpreted nature is certainly a drawback. You have to keep performance constantly in mind as you program, and have a very thorough understanding of performance, both at the algorithm and interpreter level. Tight loops are to be shunned, values need to be calculated ahead of time and cached. In short, you need to dot your I’s and cross you T’s – many areas which wouldn’t deserve a moment’s thought in C++ require careful planning.
– Choosing Pyglet
When it comes to game-oriented windowing frameworks for Python, there really isn’t a lot of choice. Pygame is a wrapper around SDL, which attempts to shoehorn SDL’s C interface into a semblance of object orientation. it is fine if you just want to push pixels around (though python’s low-level performance characteristics make that a questionable idea), but the interface is clumsy, and the library is overkill if all you need is an OpenGL context and input handling.
Pyglet on the other hand is very lean, and focused exclusively on OpenGL. Some features are still missing, in particular the ability to switch screen resolution, but other rare features are included, such as the ability to switch between windowed and fullscreen modes on the fly. Of particular use in Ashima was the fact that pyglet uses an event dispatch model for input (as opposed to pygame’s polling approach), which fit nicely with the game’s event driven logic.
What went wrong:
– Late start
If you happen to have glanced at my blog, you may have noticed that I was originally planning a 2D game, a variation on the game of Lemmings. Sometime in January, that game reached a semi-playable stage, and I discovered that it was decidedly not fun to play, and also very hard to differentiate from the original Lemmings.
After messing around with that for a couple more weeks, I couldn’t see a clear path to finishing the game, so I decided to start from scratch with a genre very dear to my heart: the space sim. Unfortunately, that left me with just two months to build a game, and in addition I found that I had severely underestimated the amount of schoolwork I would have to deal with for the early part of the semester.
In the end, the core logic all worked, and I was able to throw together the bare minimum of polish to make it appear a game, but even so it ended up little more than a proof of concept.
– Choosing ODE
The initial prototype didn’t use a third-party physics engine at all, and used a simple Newtonian flight model, with collision detection and response modelled as simple spheres. However, I decided that I needed to add accurate collisions, as the sphere model prevented the relatively small fighters from closely approaching the capital ship.
Once again, choice was severely limited, by both choice of language and time. Although there are many physics engines out there, ODE was the only with Python bindings, albeit severely out of date. It turned out that Bullet also has python bindings, but these appear to exist only as part of the Bullet-Blender integration, and I didn’t have the time to try and decouple them.
Initially ODE seemed fairly straightforward, compiling out of the box, and I was able to hack the newer features I needed into the elderly python bindings without too much trouble. After an inordinate amount of time spent tracking down random crashes deep with in ODE’s code, my opinion changed. It seems that to achieve any semblance of stability requires countless hours of tweaking constants and testing, and even after this I was unable to prevent the occasional crash.
Joints also proved to be an nightmare, although I believe this has more to do with poor memory management in the python wrappers. I eventually managed to get a single joint type, ball-and-socket, working reasonably, and was forced to use that for everything.
– Attempting Windows port
I spent some two to three days near the end of the contest attempting to port Ashima to Windows, and was severely burned by the process. My python code worked flawlessly out of the box, as did pyglet. ODE on the other hand crashed incessantly, despite being compiled from the same source with identical configuration on both Mac and Windows. Even now, some time after the competition, I have still been unable to keep ODE stable during collisions under Windows.
The next issue was with ATI’s OpenGL drivers, which are second only to Apple’s OpenGL drivers in missing features and stability. The major issue here is that the ARB_point_sprite extension just won’t work on ATI drivers (and several other programmers have confirmed this with their own applications), despite the example of several sample programs which work perfectly.
The last problem was with packaging, as I was entirely unable to coerce py2exe to output an executable that would run on both Windows XP and Vista, despite either being trivial when considered alone.
What I would do differently next time:
– Use an engine
I coded Ashima entirely from scratch, occasionally borrowing code snippets from previous projects. This was decidedly bad from a productivity standpoint, as much of that development time could have been better spent on gameplay and presentation.
Before I start my next project, I plan to either write an engine of my own, using the experience gained here, or become familiar enough with a third party engine to use it instead. Unfortunately, I have worked with a wide variety of third party engines over the last few years, and most within my budget (which is non-existant) are underwhelming – although Unity seem promising.
Another facet of this issue is that of language. While python is a joy to code in, it isn’t entirely suited to high-performance code, and I would prefer to move the more expensive processing into a C++ based engine, which would then be scriptable using python, or another high-level scripting language.
– Form a team
Between the late start, and a lack of previous projects to show off, I felt that I wouldn’t have a good chance of attracting a team to work on an entry together. I plan to start earlier next time around, and use Ashima as an example of my work, to attempt to recruit artists, musicians and even a second programmer, in order to work on a larger game, and have a better chance of finishing in time.
Where do we go from here:
I wrote Ashima partly as the beginnings of a portfolio, and partly as incentive to actually finish a game, as my track record to date is less than stellar in that regard, and my hard drive is filled with the detritus of abandoned projects.
I think I accomplished the latter fairly well. In its current state Ashima is in no way a finished game, but it is a solid prototype, with the core gameplay elements present, and a solid preview of the eventual graphics.
However, I don’t want Ashima to die here – it deserves better than that. As I find the time over the next year I plan to slowly continue developing the game. The code needs major refactoring, to undo the damage wrought by last minute additions, and I need to perform considerable play-testing and improvement to the gameplay and controls, as well as adding a decent GUI.