3D Space Combat Game
John Mitchell
CMPS 161, Winter 2011
Description:
For my final project, I created a 3D space combat game using C# with XNA, complete with multiple weapons, and enemies that move via behavioral algorithms. This game is be based heavily on the game X3: Terran Conflict and borrows models and textures from it, since model and texture creation is beyond the scope of this class.

Object movement originally used a simplified Newtonian physics model, where each object has a 3D velocity, max acceleration, and max speed. I later switched to a simpler model for ships, where they have a scalar speed along their forward vector, and acceleration changes this value. In my opinion, this gives better feeling controls to ships, and it gives better control over AI ships. I left missile movement as the original model since visually it seems to have better results.

Object and view rotation is implemented with quaternions, to avoid problems with gimbal lock when using Euler angles. It also makes controlling rotation much easier, since pitch, yaw, and roll values can be changed relative to the current view instead of needing to convert them to world coordinates.

Enemies are controlled through steering behaviors similar to those developed by Craig Reynolds. Initially, enemies start on a patrol path, implemented as seeking to waypoints. When the player moves within detection range, the enemies switch to a modified pursue and evade behavior, changed to fit the fact that they have ranged weapons they are trying to hit the player with and need to avoid the player's weapons. It is also implemented using the seek behavior, seeking to the player when attacking, and fleeing from the player when preparing for another attack pass. During the flee portion of the combat behavior, enemies will attempt to perform evasive maneuvers by seeking to a random position if their current target is facing them. In all behaviors, enemies use a modified obstacle avoidance in order to stay away from other ships.
The seek behavior is implemented using vector math and spherical linear interpolation of the quaternion orientation in order to turn the object towards the target point. If the object is within 500m of its target, it will take its velocity into account and turn towards a different point accordingly, otherwise it will turn to face its target directly. Unfortunately, due to what seems like floating point inaccuracy, objects tend to over-turn, resulting in them appearing to vibrate. Including the object's velocity only within 500m helps, but it does not completely stop it.

The player entering combat

The player firing their weapons
Collision detection uses line-sphere intersections to determine if a collision is possible. A line is drawn from the current position of a projectile to the position it will be in next frame, then tested against the bounding sphere of each object. If a possible collision has been detected, the same line is tested against a highly simplified collision mesh.
The player's ship next to its collision mesh
Engines, explosions, projectile impacts, and nebula dust each have particle systems. Engine particle systems emit stationary particles that shrink over a short period to display a short trail. Explosion and projectile impact particle systems emit fast moving particles that expand and disappear quickly to create an explosion effect. The nebula dust particle system emits large particles around the player's ship to give the illusion of being in a swirling nebula. It also aids in the player's perception of movement, since there is little else to let the player know he is moving.
My initial attempt to create a particle system were horribly slow even when there were relatively few particles, since it was implemented entirely on the CPU. I then switched to the 3D particle system sample, which is implemented mostly on the GPU. The sample runs smoothly even when there are thousands of particles at once. This implementation uses a custom vertex struct to send position, velocity, random, and time values into the shader. The shader then computes the actual position of the vertices and draws the particles. It runs even better due to its use of a circular queue for storing alll particles in that particle system, which is possible due to the fact that each particle system type must have the same life.
Since each particle system object has a limited number of particles, I created a pair of dictionaries, one that contains a list of particle systems of each type, the other contains the typename of each particle system. If no existing particle system of the specified type has available particles, the dictionary of typenames is used to create a new instance of the specified particle system and add it to the list.

The player is also provided with a Heads Up Display, which shows information including current status of the player's ship's shields, hull, and weapon energy, as well as information about the currently active weapons. In addition, the player provided with their current speed and the current speed of and distance to their current target. In addition to these static HUD elements, the player will also be provided with indicators showing the position of all objects in range.


Ship, missile, and weapon information is all stored within a set of plain text files, making adding new types to the game quite easy. At runtime, these files are loaded and interpreted, then the resulting types are stored into dictionaries to be retrieved when objects of that type are created. To add a new ship type, all that needs to be done is: process and build the model, build a collision mesh (optional, but helps performance), and add its stats to the ship file.


Texture maps include diffuse color, specular level, normals, self illumination, and reflection. The base shader and model pipeline are from the Normal Mapping sample, and the other functions are added on top of that. The sample originally used a single specular level, which I changed to be read from the specular map. Reflections make use of a cube map rendered at runtime from the skybox. All this is then combined with the color read from the self illumination map to produce the final output color.

An enemy ship exploding

A recently fired swarm missile

Controls:                         
Xbox 360 Controller (recommended)
Pitch: Left thumbstick Y
Yaw: Left thumbstick X
Roll: D-Pad X
Strafe: Right thumbstick
Accelerate: D-Pad up
Decelerate: D-Pad down
Fire main weapon: Right trigger
Switch main weapon: Right bumper
Fire missile: Left trigger
Switch missile: Left bumper
Select target: A
Nearest enemy: B
Quit: Back
Keyboard
Pitch: Up/Down
Yaw: Left/Right
Roll: A/D

Accelerate: I
Decelerate: K
Fire main weapon: Space
Switch main weapon: C
Fire missile: M
Switch missile: N
Select target: T
Nearest enemy: Y
Quit: Escape

Activate debug cam: Num5
Debug cam up: Num8
Debug cam down: Num2
Debug cam left: Num4
Debug cam right: Num6
Debug cam zoom: Num+/Num-

The debug camera makes it easier to see behaviors of the enemies in action. It looks at the center point of all enemies, and shows the curret behavior of whichever enemy the player currently has selected. It is much easier to see both the debug camera and the main window at higher resolutions, since the debug camera window takes up 500x500 pixels.
Note: ship models in this window are scaled 2x so they are easier to see from far away

Debug camera, Screenshot taken at 1280x720 resolution



Command line arguments:
screenWidth screenHeight
screenWidth screenHeight fullScreen
screenWidth screenHeight fullScreen highQuality
ex: 1024 768 false false
    will load the game in a window of size 1024x768 and display significantly fewer particles


Videos:
Combat
Avoiding ships
Patrolling
There is no loss condition, so the player can continue to fly around after dying, and enemies will not switch to combat mode

Technical Paper
Code Documentation
Readme

Source
XNA Game Studio 4.0
(Required to build source)
Installer (includes web installer for XNA 4.0 Redistributable)
System Requirements:
Windows XP, Vista, or 7
Video card that supports DirectX 9.0c
(Low quality mode tested on a Radeon HD 4570M, High quality tested on a Radeon HD 4870)
500MB available RAM
100MB free disk space




Tasks:
First: (complete) Set up the environment, allow user to fly around
Second: (complete) Add static enemies, allow user to fire weapons, implement proper movement controls
Third: (complete) Implement collision detection for projectiles and ships
Fourth: (complete) Implement behavior for enemies and missiles
Fifth: (complete) Implement remaining HUD items, change any previous versions to final
Extra: Add additional enemy and weapon types (4 enemy, 3 missile, and 4 weapon types complete)
Extra: (incomplete) Implement automatic rear turret
Extra: (incomplete) 3D radar