My interest in space games dates back many years, when I played Elite for countless hours on a Sinclair Spectrum. In later years, I found myself enthralled by Frontier, the ‘sequel’ to Elite, and the vastly underrated plot-led combat sim Warhead. Both of those games more or less typify how I expect a space game to work: convincing physics, true 3D and immersive environments.
The thing that brought these old gaming memories back was a recent remake of Elite written by Giles Williams, the punningly-named Oolite. As much as I liked Giles’ game, I really wanted to see a space sim with more graphical realism and a sort of crude, industrial look. Also, where many space games revel in high-tech heads-up displays, I wanted to place the player directly in the cockpit, looking around at the clunky hardware as well as out at the stars.
I’m always reluctant to exactly copy existing games, so I began to think of ways to make my game stand out as I laid down the design for the gameplay. I decided that it would be most interesting to shy away from the usual ‘dogfights in space’ gameplay and go for something a little more unusual: a more passive kind of gameplay where you have to rescue asteroid miners from certain doom. No guns, no shields, just a chunky industrial space tug, a set of mining tools, and your flying skills to keep you alive. Having settled upon this cursory design, I began coding.
What Went Right
Starting from Scratch
One of the first decisions I made was to drop almost all the code I had ever written before. I had wanted to take this step for quite a while because I had become weary of working with the same rotten old code, which I first started writing several years ago. I used this code to make Super Phoenix and Yoink, and it works adequately as far as it goes, but it has deep seated design problems that I’ll probably never manage to eliminate. By starting afresh, I hoped that I would be able to create a clean, focused basis upon which to work, and that would help me to make a better game.
I also wanted to try several technologies which were new to me. My earlier games are still compatible with Mac OS 9, using the CFM runtime and the Carbon API. For Rescue, I thought I’d go a step further and build a Mac OS X only Mach-O game for the first time.
Using Standard Libraries
Having disposed of my own source code resources, I decided to replace it by utilising as much freely available, widely used source code as possible. I mainly wanted to avoid reinventing the wheel, but I also hoped to learn some new skills and techniques by delving into other people’s code.
I chose SDL as the foundation of my application. It has a good track record, it’s popular and as a bonus it’s abundantly cross platform. SDL also has an extensive selection of standard (and not-so-standard) additional libraries, and I picked two of the best respected-_SDL_image_ and _SDL_mixer_-to handle image file loading and sound, respectively.
For my math and physics code, I decided to try WildMagic, a huge and rather complex C++ library. WildMagic had a large number of features which I didn’t really want to use, such as a built-in scene graph and an application framework similar to GLUT, but I was able to use the functionality I wanted (vectors, quaternions, matrices, intersections and so on) without picking up too much unwanted overhead.
I needed a way of loading 3D models, something which I haven’t even thought about since the last time I used QuickDraw3D. Because I had no experience in writing my own model loader, I decided to use the OBJ format loader written by Karl Berg, another member of the iDevGames’ forum. I found his loader particularly interesting because the example program supplied with it showed a spaceship model with attractive specular highlights and an illumination map.
For other data files, I decided to use TinyXML, a simple but effective XML library written in C++. I used it in the creation of my uDevGames 2003 entry, Yoink, so I was already satisfied that it was the right tool for the job.
Optimization
I wanted to make an infinitely large, densely populated asteroid field with a large visibility range. This was going to cause obvious problems in terms of the frame rate, so I had to use some tricks to keep things moving quickly.
I used simple cubic space partitioning to control the culling of invisible objects. Partitions which are outside the camera frustum are not drawn. I had considered using octrees instead of plain partitions, but I decided that it would be too complicated and not necessarily much faster. However, I did go on to use an octree routine to lay out asteroids in space partitions in a way which prevented two rocks from overlapping.
In addition to this, I needed to cull objects by distance. I was only able to render about a hundred asteroids before things started to get too slow, but this meant that either my visual range was very short or the asteroid field had to be very sparse. I dealt with this by reducing distant rocks to a silhouetted polygon on a billboard, and using fog and careful scaling to make the level-of-detail pop less noticeable. It wasn’t clever, but it allowed me to display several hundred asteroids instead of just a few.
Elsewhere, I used very few optimizations. Apart from having to make some minor changes to WildMagic to get a big speed increase, I didn’t do anything much to make things efficient, so the game wasn’t very fast or smooth on slower computers. Machines with old graphics cards such as the ATI Rage 128 were almost bearable, but most people weren’t able to tolerate the game at such a low frame rate, so I necessarily cut a lot of users with lesser machines out of my potential audience.
Teamwork
When I embarked upon the development of Rescue, two weeks after the start of the contest, I was really only using the contest as a chance to experiment in a formal setting. I didn’t even sign up for a several weeks. However, out of the blue I was contacted by a freelance musician, Mikko Tarmia. He said that he had seen Rescue and wanted to write music for the game. I was flattered that he liked what I had done and I really liked the sample pieces of music he showed me, so I was very keen to ask him to contribute.
It then struck me that my little game experiment was now much more serious. It wasn’t just my effort and reputation on the line, but Mikko’s too, so I felt that there was no way I could afford to let him down by slacking on my part of the deal. From that point, no matter what happened, I was determined that I would do my best to reach the end of the contest without quitting.
Later in the contest, I realized that, while I had nice spaceship and asteroid models, as well as pretty star and nebula textures, I was going to have a hard time adding textures to the 3D models. My modelling software, form-Z, is rather good at low-poly modelling, but is lacking in features for manual UV mapping. I could also see that I was going to be pushed for time if I concentrated too much on making textures. Having already formed a small team, I was much less reluctant to ask for extra help than I had been on previous projects. With this in mind, I asked my old friend Brian Smith, a skilled graphic designer and 3D model maker, to join the team and work on the textures.
I had never developed a game as part of a team before so all of this was a whole new experience for me. I’m pleased to say that I found the whole collaborative working process very smooth and easy to deal with. My teammates were both very professional and delivered high quality work right on time, and they were thankfully tolerant of my requests for changes and criticism! Mikko and Brian wrote their own accounts of their parts in the project, which you can read below.
What Went Wrong
Too ambitious
As was the case with Yoink in uDevGames 2003, I found that the game I had designed was much more complex and time consuming than I had imagined. I still find it difficult to perceive how long things will take at early stages of the project.
My failure to devise a schedule and stick to it meant that many features had to be omitted from the game, so much so that the resulting gameplay was nothing like what I originally envisaged. I had planned to make Rescue a much more innovative game, in which stealth and lateral thinking were your only weapons against a much more powerful enemy. Among some of the features I had to omit:
- Giant enemy battleships which would patrol the asteroids looking for mining installations to destroy. This would have been quite a significant part of the programming work, as it’s very difficult to make an effective AI which is fun to interact with. I expect that developing the AI would have required a lot of tweaking to get things just right.
- Tools such as limpet mines which could be deployed from the player’s ship to distract or delay the enemy. Also, I wanted the player’s ship to be able to pick up objects with its robot arm and carry them around. I mainly omitted these features not because they were difficult, but because they would have served no purpose without an enemy to defend against.
- A mothership which would drop the player off at the beginning of each stage and pick them up at the end. It would loiter in the background and act as a drop-off point for evacuated miners. I was very disappointed to have to leave the mothership out of the game, but Brian and myself agreed that there wasn’t enough time to build and texture another detailed spaceship model. In the end, I resorted to having the player accelerate into hyperspace instead, and this was at least an unusual approach to this particular sci-fi cliche.
- The most ambitious thing I had to omit was the planned character interaction and plot. I wanted to have a co-pilot character sitting in the other seat of the cockpit, and this animated character would act as in-game help, telling the player what to do next and explaining how to perform certain tasks. Beyond that, I had imagined that I could have a storyline played out in animated 3D cutscenes, using the same characters. Unfortunately, all of this had to go because it was the lowest priority of all. However, I wish I had been able to add some kind of in-game help in the absence of the co-pilot, since many players clearly had difficulty understanding how to dock the ship and how to get into hyperspace.
Scheduling
Another problem in common with last year’s project was the proper scheduling of the development process. I don’t particularly like to work to a fixed timeline, so I spent my first two months producing code and game assets with no regard to the deadline.
Much of the work was comparatively easy and quick to produce, since I had already written similar code for my other games. For example the time-based animation system and simple scene graph were quite elementary and didn’t take long at all. On the other hand, several essential elements ballooned out of control and ate up significant chunks of the development time and my patience. The collision detection system was an especially major source of wasted time.
I also spent a whole week doing nothing but trying to redesign the cockpit model. I had an existing cockpit model which appeared in early versions of the game, but I wanted to replace it with one that was much more immersive and full of equipment. This became a huge source of stress and annoyance because I simply could not get the result I had in my mind. In the end I had to compromise and revert to the version of the model which was closest to my original intent.
Collision Detection was Problematic
I chose to write my own collision detection system from the ground up instead of using a library such as ODE. This seems odd with hindsight, as I was trying to utilize third party code as much as possible, but I suppose I was afraid of its complexity. I have since discovered more about ODE through the experience of other developers, and it seems that it is indeed fraught with tricky problems. Maybe I made the right decision for that moment in time.
I designed a rather complex but crude mechanism which utilised WildMagic’s intersection routines to handle interactions between primitive spheres and capsules, groups of primitives, and rays. It took about two or three weeks to write because I kept deciding that I had made design mistakes and refactoring it. Even after all that hard work it still didn’t work properly, and many of the features were never used in the finished game because they weren’t reliable.
As it stands, my collision detection system is still too crude for my liking, and this shows in various places. For example, the requirement that all objects must be capsules forced all of the asteroids and buildings to be roughly capsule shaped. Unfortunately, you can sometimes still see weaknesses in the system when you get close to irregular objects while looking at the external view. This code will all need replacing in some future version.
A Lack of Refinement
While I managed to make good headway into the technical issues of making the asteroid field limitless and the spaceship fly the way I wanted, I didn’t pay enough attention to the little niceties that gamers expect. The title, end of level and game over screens are extremely lightweight in their presentation. There’s no in-game menu; everything is just ‘press a key to continue’ (and it doesn’t even tell you to do that!). Also, there are no in-game preferences and there’s no way of redefining the controls. I did manage to have an editable XML preferences file, but that’s probably too technical for ordinary gamers.
As I expected, I’ve had quite a lot of feedback asking for redefinable controls, so I have put this on my to-do list. Of course, I don’t intend that the game will continue to have a horrible in-game GUI—I shall also deal with this in time.
I did have a little success with the manual I wrote. The final version of the manual was illustrated and had detailed instructions to help novice pilots figure out how to land and escape into hyperspace. I know that many people won’t read the manual, but I’ve had positive feedback from those that did, so I’m happy that it wasn’t a waste of time.
Working with the Limitation of Other People’s Code
There were several occasions when I was forced to deal with problems that were not of my own making, but which came instead from the way the various libraries and other incorporated code worked.
The first thing which hampered my progress was a strange bug in CodeWarrior 8.3 which prevented _SDL_image_ and _SDL_mixer_ from being linked to my application. A little research revealed that the problem was caused by the underscore in the libraries’ names. I dealt with this quite easily by making my own versions which were renamed to remove the underscore.
The only thing which concerned me about this modification was compliance with the license. Since the SDL libraries were released under the LGPL, I didn’t want to fall afoul of the license’s rather complex wording. My modifications were extremely minor, so I simply asked Sam Lantinga, the author of both libraries, for permission to make the changes without getting embroiled in the licensing concerns. Much to my relief he gave his permission!
WildMagic also needed modifications, although it was less worrying to me because its license permits almost any modifications. The problem was that the programmer had inexplicably decided to use the memcpy() function as a means of implementing copy constructors and assignment operators for almost every class. For frequently used types like vectors and quaternions, the overhead of calling memcpy() all the time was substantial and showed up as a large blip in Shark profiles. At the time, I felt that Rescue wasn’t running fast enough on slower computers, so I tackled this by simply commenting out several of the most commonly used constructors and assignment operators and rebuilding the library. This increased the speed of the game by no less than 30 percent, so in the long run this was a great benefit!
Karl Berg’s OBJ loader was the other component that I changed, and again it was helpful that his license amounted to the freedom to make any changes. In its original state it was only able to support BMP textures and didn’t look for texture and material files in sensible places. I addressed these issues by adding support for _SDL_image_ and adding a function to return the application bundle’s resources folder.
At some point I would like to make some more radical changes to Karl’s code. His coding style, essentially C with classes, doesn’t really marry well with my own, and there are some outstanding bugs I’d like to fix. I plan to strip down his code to the bare parsing routine and build it back up in a way which is more suitable for my purposes. I’d especially like to add features which allow code to examine the model geometry, as this would be useful for collision detection.
Last Minute Damage Control!
I saw this coming but I somehow didn’t manage to avoid it: I reached the uDevGames submission deadline and I still didn’t have any gameplay to speak of. You could fly the ship around, pick up miners and hyperspace to the next level, but there was no threat and nothing to force you to take any risks, so if you were a careful driver you’d be able to play the game forever.
About three hours before the deadline I took the drastic step of adding a simple time limit. This was something I really didn’t want to do because it made Rescue seem very similar to Asteroid Rally, Matt Diamond’s game from uDevGames 2003! At this late stage I saw it as the only way to turn my basic spaceship flight simulator into something like a proper game. Thankfully, it only took me a few minutes to implement the time limit itself and the ‘out of time’ game over screen. Once in place, the time limit did indeed have the desired effect, and it was now necessary for the player to rush from one mining installation to another to complete later levels in time, putting their ship at risk in the process. After a little tweaking of the difficulty level, I finally reached a stage where my game was fun and exciting for me to play, not just mildly interesting! Satisfied that the game was now just about acceptable, I packaged it up and submitted it just one hour before the deadline.
Tools
I used the Metrowerks CodeWarrior 8.3 IDE to write and build the game. However, in an attempt to make the source code more accessible to the community I’ve since made an Xcode project as well. This was a useful learning experience in itself!
The spaceship exterior and interior models, as well as the buildings and some of the asteroids, were built using form-Z, a highly accurate and complex modelling package I use for my commercial visualisation work.
Brian used Cinema 4D for UV mapping and texturing the models, as well as making some additional asteroids.
Carrara 3 was used to make the stars and sun. I had hoped to make better use of Carrara since it was one of the prizes I won in last year’s contest, but as it turned out I wasn’t able to learn its polygon modelling feature set in time to do something useful with it. I used Photoshop CS to make the font and various other graphics, while Brian used Photoshop 7 to work on the textures.
For audio, I used Reason, another prize won in uDevGames 2003, just once to make the first sound effect! Had Mikko not come on board to make the music and the rest of the sound effects I would have had an opportunity to put it to better use. Never mind, Yoink still needs music!
Summary
Now that that the contest is over, I can clearly see that I made many of the same mistakes as last year. I devised a game idea which appeared at first glance to be concise and manageable, but which with hindsight couldn’t possibly have fitted into the three month development period. Maybe if I had unlimited amounts of free time it might be possible, but when I have to fit all this hard work around a full time job and other obligations and interests, it’s can’t be done.
Still, even though the resultant game didn’t match my original vision, I’ve benefited in several ways. I’ve learnt a lot about several very interesting APIs. I’m now very interested in using the SDL libraries and WildMagic in future projects.
I’ve worked as part of a development team. I’m used to teamwork in my day job, but it’s a bit of a breakthrough for me to be able to share my personal creative work with other people. It has been enlightening to work with other people’s opinions and contributions in mind.
My objective of making a reasonably complete space game engine has finally been achieved. I (and others) can now build upon this project to make more sophisticated games. I now have another partly finished project to hang up on my web page!
Where shall I take Rescue now? I plan to add all of the features I was forced to omit before I go any further. Replacing my home-cooked physics with ODE, renovating the OBJ loader to suit my needs, building the enemy ship models, putting them into the game and giving them AI…all of those things are achievable now that the deadline has passed and I’m free to work at my own pace. It seems that Mikko and Brian are both interested in seeing the project completed, so it looks like I’ll be working hard on Rescue for the next few months.
Neil Carter
www.nether.org.uk
Making the Music and Sound
Mikko the Musician
I almost cancelled my intention to participate in this contest because I had a great deal of work with other projects going on. But then a big project was cancelled and I had some time again. I found Rescue, which is sort of a slow action game (I was actually looking for an action game), and contacted Neil.
After trying the early version of Rescue, I quickly had a vision of what the music would be like. Neil didn’t want it to be too modern in terms of its harmony, so I followed this rule. I’ve usually created this kind of stuff by using orchestral instruments only, but this time I wanted to add some electronic sounds to it. The ambient in-game track sounds electronic, but actually most of the sounds in it are “real” (low strings, choir). The main theme reappears in the action track too, to make the game audio more coherent.
I also promised to help Neil with sound effects, so I made them after the music was ready. I didn’t notice the rapid passage of time and was actually a bit rushed to finish them before the deadline!
I didn’t have any problems with this project. Communication was great and things worked out nicely. The only thing I got a little worried about was when Neil decided to change the purpose of certain music tracks to deal with changes in the gameplay. Fortunately the game developed in a way that meant we didn’t have to throw anything out. Just some of the sound effects I made have not been used in the game (yet).
Texturing the Models
Brian Creates the Eye Candy
I was happy to accept when Neil asked if I would like to produce textures for Rescue. Like Neil, I tend to start lots of projects but only finish a few and so the competition sounded like a good incentive.
The first step was to make sure we could transfer Neil’s models from form-Z to the 3D package I use, Cinema 4D, UV map them and then export the models as Wavefront .obj files which the object loader library could use. We soon discovered Cinema’s .obj file exporter reversed the surface normals. This was easily fixed by inverting the models’ normals before exporting. There also appeared to be a problem with the UV mapping in Rescue. By examining the UV data in Cinema 4D’s Structure Manager I discovered that the first UV coordinate was being zeroed when the models were opened by the object loader library. Neil and myself decided that this glitch should be worked around by editing the .obj model files (copying the first set of vt coordinates to the end of the UV list and then updating all references to it in the f polygon list) to save time hunting it down. Cinema 4D also didn’t export material files with the .obj model files and so manual file editing was required to construct them and link them to the model files.
The most time consuming part of my work was UV mapping the models. This was done in Cinema 4D with the freeware plug-in, UV Toolkit. The asteroids proved tricky to flatten as they had continuous surfaces. I decided to minimise variation in texture scale and shearing at the expense of creating seams. I also chose to stick to a single 512×512 texture for all the asteroids to save time and conserve VRAM. To change the texture scaling to fit the different sizes of asteroid I first mapped the larger asteroids to the full texture space and scaled down the smaller ones proportionately. However, this resulted in a very blurred texture on the large asteroids. I later realized that the object loader would tile the texture if the UV coordinates were outside the 0.0 to 1.0 range and so the smallest asteroids were assigned the full texture space with the larger ones scaled up, to a maximum of 4x for the biggest ones.
For the buildings and tug UV maps I found the best method was to break down the model’s surfaces based on the most suitable type of projection. For example, first I assigned UV coordinates to all the surfaces that could be mapped with flat projection, then all those that need cylindrical projection and so on. With all the elements mapped the largest surfaces were placed and scaled within the UV map. Finally the smaller elements were slotted into the remaining spaces. Much fine tuning of elements’ scales was required to optimize texture space usage. For most models the texture space assigned over its surface needed to remain constant. However the tug cockpit model was to be viewed from a fixed position so I skewed the scaling so that the surfaces nearer the viewer were allocated more texture space.
The textures themselves were based on reference images supplied by Neil (a photo of an asteroid, a shot of the Space Shuttle cockpit and so on) and discussions that occurred as the textures where developed. I took screen shots of the UV maps in Cinema 4D and opened them in Photoshop. All the textures were painted at twice their final target resolution. They were rendered using a mixture of filled and stroked selections and hand painting. Public domain photos from the web were overlaid on the painted texture to add detail to the metal, concrete and stone surfaces. I also placed blurred highlight lines along the model edges where I wanted emphasis.
Overall, given the limited time I had available to UV map and texture the models, I am pleased by the results. I would like to get involved in more game texturing in the future and am sure that what I have learned from this project will come in handy.
Brian Smith
www.steampunk.demon.co.uk
www.mikkotarmia.com