Do you dream of writing the next hit game title but aren’t sure how to get started? Are you interested in game development just for the fun of it? Take a close look at a versatile cross-platform gaming engine that’s freely available for the beginning game developer.
A (Very) Brief History of 3D Gaming Engines
In gaming, more so than any other programming discipline, it is important to specify the platform correctly from the start. Will you support Windows, Linux, and OS X? Isn’t using OpenGL enough to get you there? OpenGL was designed in the early 1990’s for $25,000 Unix CAD workstations and later adapted to Windows and low-end platforms as the gaming industry drove the cost of graphics accelerators down from $2,000 a pop to the $150 mass-market price point you see today.
Indeed, many people would cite the revolutionary game Quake, written for OpenGL in 1996, as the direct cause of this. However, achieving Quake-level gameplay standards required more: world-class audio support, network connectivity, user-input device support, and real-time management capabilities—just to name a few. The solution for both requirements, cross-platform support and the extras that make a game exciting, is a decent game development platform.
Simple DirectMedia Layer for C++, Java, and More
Well, that’s all very interesting history, but it doesn’t really address the question of where fragging coders should start: Not every game is going to be a Quake clone. One option that has been touted for its many virtues is Simple DirectMedia Layer (SDML). This cross-platform multimedia library provides low-level access to audio, keyboard, mouse, joystick, OpenGL, and 2D video framebuffer. SDML supports most every platform I can think of, including Linux, Windows, all MacOS variants, WinCE, Dreamcast, and others. It shows up in MPEG players, hardware emulators, and many popular games, including the award-winning Linux port of Civilization: Call To Power.
SDML is written in C, but works with C++ natively, and has bindings to several other languages, including Ada, Eiffel, Java, Lua, ML, Perl, PHP, Pike, Python, and Ruby. The sky is the limit with SDML, which happens to be the engine for my favorite open source flight simulator, GL-117 (see Figure 1). In fact, 513 games currently are built on top of the SDML engine and registered on the SDML homepage.
Figure 1. The View from GL-117
Tunnel Vision Demo Program
The best way to get inside a game engine is to look at some sample code. Take a brief look at a 2-D tunnel-type display in SDML (see Figure 2) to see what you can do in just a few lines of code. This example might be something you use for a screen-saver, music visualization, and so forth. I’ve trimmed the actual drawing code for brevity. Follow my comments for a description of how SDML works:
#include "Tunnel.h" // SDL Stuff SDL_Surface *screen; SDL_Surface *bBuffer; SDL_Surface *Image; SDL_Rect rScreen; SDL_Rect rBuffer; // -------------------------------------------------------------- int main (int argc, char **argv) { int flag = SDL_SWSURFACE; // Requests a software surface. // Software surfaces are in // system memory, and are not // generally as fast as hardware // surfaces #ifdef WIN32 int fullscreen = MessageBox(NULL, "Show Full Screen (y/n):", "Screen Setting", MB_YESNO); if (fullscreen==IDYES) { flag |= SDL_FULLSCREEN; // Take over whole screen, if // user desires } #endif Tunnel_Timer(); // Read initial system clock SDL_Init( SDL_INIT_VIDEO ); // Initialize just the video // subsystem // Set screen to 320x240 with 32-bit color screen = SDL_SetVideoMode( 320, 240, 32, flag); // Request hardware buffers for the screen surface, if available bBuffer = SDL_CreateRGBSurface( SDL_HWSURFACE, screen->w, screen->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); // This is the seed image that you will convolute when you get going Image = SDL_LoadBMP( "tunnel_map.bmp" ); Image = SDL_ConvertSurface(Image, screen->format, SDL_HWSURFACE); rBuffer.x = 0; rBuffer.y = 0; rBuffer.w = bBuffer->w; rBuffer.h = bBuffer->h; // Ignore most events, including mouse, and disable the cursor SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE); SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); SDL_ShowCursor( SDL_DISABLE ); Tunnel.Set( 320, 240 ); // Tunnel will fill the whole buffer Tunnel.Precalc( 16 ); // Inner circle diameter while (SDL_PollEvent(NULL)==0) { float fTime = Tunnel_GetTime(); // Surfaces must be locked before modification, especially // if the buffer resides in the graphics hardware memory SDL_LockSurface(bBuffer); SDL_LockSurface(Image); Tunnel.Draw(bBuffer, Image, 180*sin(fTime), fTime*100); SDL_UnlockSurface(bBuffer); // After updating, you may // unlock SDL_UnlockSurface(Image); // Push the buffer out to the screen draw area and force // a repaint SDL_BlitSurface( bBuffer, NULL, screen, &rBuffer ); SDL_UpdateRect( screen, 0, 0, 0, 0 ); } Tunnel.Free(); }
Figure 2. Spinning and Twisting 2D Tunnel Demo