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 |
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 |