My most recent project started out pretty simply. I bought a wireless Xbox 360 controller for Windows. The “for Windows” part was why I bought it; I don’t have an Xbox 360. But Microsoft provides what they call the XInput interface to the controller, making it very easy for someone off the street to write programs for the PC that accept input from the controller.
This sounded like fun, and the interface itself turned out to be very simple… but then I needed an application, something to actually do with the controller. This didn’t take too much thought. I remember what was then, and even now almost 20 years later still is, one of the best video games for the PC, Star Wars: X-Wing. This was actually a pretty straightforward space flight simulator, but with great game play, story line, and sound effects and music.
As usual, I am not really interested in game development as much as I am in the interesting mathematical and programming problems that live behind the scenes, so to speak. But I thought it would be interesting to write a simple space flight simulator similar to X-Wing, using the Xbox controller for the joystick input.
You can download the result here, which includes instructions, source code, and Windows executables. But also as usual, this should compile on *nix platforms as well, wherever FreeGLUT/OpenGL is supported. (The original motivation for the project was to use the Windows-specific XInput interface to get at all 6 axes and 14 or so buttons on the controller. But ever a fan of portability, I ended up sticking with GLUT’s more generic joystick interface, which should work with other controllers on other platforms. I also included keyboard controls to play around without a joystick.)
This all started with a desire to experiment with simple joystick input. But it soon turned into an experiment with a neat 3D graphics technique that I had not heard of before, the “skybox.” The idea is very simple, as most good ideas are. If you want to render an image from the cockpit of a spaceship, then in addition to the other nearby spaceships, or obstacles, or whatever else must be drawn in the field of view, adding distant stars helps a lot to provide a sense of rotational motion.
One approach to doing this would be to include hundreds of individual distant star “objects” in the scene. This is not very efficient, since it requires performing the coordinate transformations from world to camera coordinates for every star, for every frame of animation.
A skybox is a simpler, much more efficient, and just as effective solution. It involves texture mapping, or rendering a flat 2D bitmap image onto the polygonal surface of a 3D object (think of pasting a decal onto a model). Graphics cards can perform texture mapping very efficiently, even if the 2D image is very complex.
A skybox is just a texture image of a star field, mapped onto the inside faces of a cube. Instead of transforming and drawing hundreds of individual stars every frame, we draw hundreds of stars on six flat black images ahead of time. Then every frame, we just texture map the six images onto the inside of a cube that translates– but does not rotate– around with the spaceship. We draw the star field before drawing any other “nearby” objects, so the stars will be appropriately occluded.
A couple of final notes about the “bad guy” TIE fighters in the simulator. First, I chose TIE fighters because (a) I had Star Wars in mind the whole time, and (b) a TIE fighter works well as a simple wireframe model, particularly the wing solar panels. Second, the “autopilot” for the computer-flown fighters was mostly an afterthought, but is an interesting mathematical problem in itself. I made up some extremely simple rules that led to reasonable, if somewhat drunken, flight characteristics.