- HoverTank - Augusto Roman CS248 - Autumn 2001 --- Note: The code and binaries can be found at: http://www.stanford.edu/~aroman/HoverTank --- ---------------------------------------------------------------------- Hovertank is a fast-paced, violent, carnage-intensive multiplayer-only hovertank-combat game. It was designed to be simple to setup, simple to play, and to be fun-inducing in a very short time span. It was also intended to be a complete game with an included intro, intuitive menu system, easy server hosting / joining capabilities, and in-game chat (taunt). This game was designed in the 4 weeks allotted for the project. During that time, a friend of mine visited from out of town for a week and I got very little done. During the last 1.5 weeks, I did almost nothing else (including sleeping/eating/going home). ---------------------------------------------------------------------- The Code: To compile the code, you should just need MS Visual C++ v 6.0 or greater. Unzip the source zip file with subdirectories and load /Hovertank/Hovertank/Hovertank.dsw. The project for the game is the "master1" project (never figured out how to change that name). You will need glut installed before compiling this project. You will also need the DirectX 8.1 SDK installed. The Server project is for a dedicated, text-only server and not required for gameplay. The glutar project is a glut-like support code that I developed in order to have more control over the system -- I needed the window handle for a number of tasks and glut didn't provide that. So I (basically) re-wrote it. Glutar ("Glut A R") is mostly call-compatible with glut. When running: The program expects the following directory structure when running: \HovertankGameDirectory: \Data: *.png *.wav *.mp3 \Prog: *.exe *.dll *.bmp Controls: Included in the game, under the settings menu. ---------------------------------------------------------------------- Advanced Features: * Networking: The game uses DirectPlay 8.1 for its networking. This code was developed solely from the "SimpleClient/Server" example in the DirectX SDK as I could not find a single tutorial on DirectX 8 anywhere on the net. That was very irritating. Sifting through these sample programs was a nightmare because they were horribly and almost inextricably linked in with window-management code. Ugh. So, I basically ripped out the relevant code and added stuff necessary for my game. The result, though was very nice. It allows easy hosting and joining of games, automatic name resolution and a very simple interface to joining games! Also, the structure of the game code was designed carefully to allow playing over low-bandwidth and high-latency connections. In theory, it should be fully playable over a modem! The client/server architecture also scales nicely. I arbitrarily decided on an 8-player limit, but the only thing that changes to increase that is a single #define statement! Laggy clients don't slow the rest of the players down. The server actually runs its own, definitive copy of the game and updates this copy according to received input snapshots from clients. Clients are updated up to 10-15 times per second or as often as possible. Between updates, each client predicts the motion of all other clients and the local client at the maximum capable system framerate. Because this prediction takes into account acceleration (i.e. "quadratic prediction"), it typically has a very accurate guess for the short periods of times necessary (~100 ms) and updates from the server typically have no noticeable effect. Other optimations include syncing between the clients and the server upon joining -- the trees are randomly placed around the map (see below). Since I wanted all the clients to see the same trees, rather than sending each location, only the random seed is sent and all clients can regenerate the tree locations. The game also allows players to chat with each other as well as displaying game notifications (such as player joining / quitting , music control) in the message display. I think that the scrolling effect looks very cool. * Graphics: The game uses OpenGL exclusively for the graphics. The terrain is a heightmap that is statically compiled into a display list and display without any view-frustum culling. I actually incorporated the ROAM dynamic terrain LOD algorithm into the game, but it turned out to be _slower_ than simply compiling and displaying the entire landscape as a display list. Since I was after speed, I had no choice but to drop the ROAM stuff. It's still in the code -- check for the "USE_ROAM" #define. I have a fully-functional and fairly powerful particle engine in the game, used to make the explosions, the dust-kickup from the tanks, and the fires for the trees. The particle engine is divided into 3 parts: An individual particle, a particle emitter, and the overall particle engine. The engine contains several "general-purpose" particles and a number of emitters. Each emitter contains its own group of particles. There are several different kinds of emitters (one for each desired effect), and each emitter can be "attached" to any MobileObject structure -- tanks, projectiles, whatever. When objects die or disappear, they unattach themselves and the particle emitters die off. Emitters can also die due to a lifespan timeout or exceeding a total particle count. Particles and trees are billboarded. The OpenGL fog effect is included. Alpha blending -- I went nuts with the alpha blending, it's such a cool effect. I was especially happy with the way the menu came out. The entire menu system was rendered in Orthographic projection without depth-buffering (just order of drawing) except for the rotating world on the bottom. That is done as follows: 1) The world is rendered with a squashed viewport and an appropriately adjusted FOV 2) And alpha map is textured over the rendered image replacing ONLY the alpha values 3) The menu background is painted over the image, using the destination alpha as the blend factor By doing this and adjusted the alpha value of the alpha texture map, it's easy to get it to fade in and out. Very very cool!! * Sound: The game uses the BASS sound library for the sound code. This library is very nice as it allows both wav files to be played as well as background MP3 songs. Very cool. In addition, the library allows adjustment of the volume, pitch, and panning of individual sounds. Using this, this game includes volume adjustment based on distance for weapon fire. Also, the pitch of the hovering engine sound is adjusted based on the current speed. In-game control of the current song is incorporated. * Models: The models were made using Lightwave 3-D, then imported into the game using 3D Exploration to convert the models into OpenGL code. That program is incredible. The generated display-list files need only a few slight changes (making functions static to avoid conflicts, changing main function name) before they could be used. Because of this, it took approximately 5 minutes to add a new tank into the game. * Menu / Game control: Personally, I've always hated games (or programs) that are difficult to configure. It's a personal goal of mine never to require users to fiddle with text files or whatever to configure or run a game. Thus, I went to great effort to include video- mode selection, player name and tank selection, and the hosting/joining servers right into the game. I did my best to make it seamless as well, such that starting a server actually spawns a separate thread in the game. The program automatically queries windows to find available video modes to show in the settings menu. * Collision detection: The collision between weapon-fire and the tanks is done solely by radius. This was decided by two factors: (1) It's fast to do. (2) It didn't take long to code. I felt that adding per-polygon detection for the game wouldn't add much to the gameplay (you'd never notice over the network effects anyways) and would be a real pain to code. Collision detection with the ground is done by interpolating the height values between gridpoints. * Physical modeling: All moving objects are described by their current position, velocity, and acceleration. Typically, only the acceleration is set in each game loop. The others are simly updated according to the elapsed time. This also causes the game to run at approximately the same speed on all computers. * The camera: The game camera is another big deal (for me ;). Another of my goals was for the player not to ever have to worry about adjusting the camera on their own. Instead it whips around smoothly and continuously to allow the player to see the necessary action. It also sweeps nicely from from the old tank's location to the new tank when a player dies and respawns. Getting the camera to act properly in a number of different situations (far away, close up, rapidly approach, hitting the ground, etc) as well as acting consistantly across machines of different speeds was something that took me the entire span of the game to get a result that was satisfactory. Throughout the game development, I would post the current version of the game on the web for my friends to download and try out. Almost every time I got a list of things that need to be fixed, the camera movement was in there. Probably still is. ;) * Procedural modeling: The trees are randomly placed around the map using a simple procedural technique that attempts to cluster the trees into forests. It also avoids putting trees in water. The routine is synchronized between the client and server via the random seed. Oh yeah, the trees also die when they catch on fire and after burning out. :) * Lighting: Everything is dynamically lit. Because the terrain is rendered in a brute-force fashion without pre-computed lighting (it's still fast!), it would be easy to add a "night-mode" to the game. In fact, had I another day or so, I would have done this. Headlights or flashes due to explosions -- it would be very cool. ---------------------------------------------------------------------- Credits: Really, I can't say that I worked "alone" on this project. Without the help of these people, I would never have gotten close to getting as much done as I did. [ Friends & Family ] Edgar Roman (brother) - Inspiration, ideas, advice, models, play testing Hrefna & Finnur - life support during the last week Kerri Kusza, Hrefna & Finnur - Play testing All of the above - Players during final presentation All my friends & family - Support and encouragement [ Resources ] Books: \"The Red Book\" - OpenGL Programming Guide, 3rd Ed. Real-time Rendering Incredibly useful game development sites: Nehe's Game Tutorials (nehe.gamedev.net) - These are incredible. (also, the rest of www.gamedev.net!) Flipcode (www.flipcode.com) - This site rocks Gamesutra (www.gamesutra.com) - Also a useful side 3D Gate (www.3dgate.com) - for textures ROAM (www.llnl.gov/graphics/ROAM) - For the paper on ROAM and the simple implementation by Bryan Turner off of Gamesutra) Sounds - acquired by scouring the net for free sound effects [Libaries / Code] GLUT32 (Nate Robins) - Used as a starting point for everything. nVidia tech demos - Used as reference and inspiration, source of glh and libpng glh (includes zLib) - used for everything! The vec and array clases especially! libpng - used for loading all my images ROAMsimple - used for dynamic LOD, later discarded. Probably my fault it was so slow. BASS (www.un4seen.com/music/) - used for all sound. Awesome.