Language: C#
Library: XNA
Programming/Design/Menu Art: Daniel Zeligman
Sprite Art: Xin Guo
Music: Keith Stacey
Particle Engine: Mercury Particle Engine by Matthew Davey
Fusion is a single-player vertical scrolling shoot-em-up.
The player controls a single space ship and must fight to survive an onslaught of alien waves.
The aliens themselves are of the race fuzors. When a fuzoor alien dies it produces a fusion charge. There are three different fusion charge types : red, green and blue. These charges fuel the player's powerful weapons: a piercing laser, a multishot-machinegun, a exploding rocket and a nova-bomb.
Features:
- Flexible collision detection
- Amazing particle effects
- Finite state automata (FSM) unit controllers
Screenshots:
Programming ChallengesFusion was my first large game project. I had little experience with C# prior to development, as well as little experience with a game architecture.
My initial design involved completely different concepts from what the end product contains. I changed the base game idea about two or three times during development, which
then required me to refactor the core game design. With my future projects I will iron out a much more detailed design prior to development in order to speed up actual development
time.
In terms of the architecture I knew that I wanted to use a standard inheritance-driven base to experience its advantages and disadvantages. This decision required me to rewrite a few of the base abstract classes a few times, but I am thankful I did. The structure I have is quite simple, when adding more enemies, weapons or projectiles it doesn't require much change.
For example, a new enemy ship would exist within a hiearchy similar to : GameObject->Enemy->newShip.
The updating, drawing, collisions and other related code is inherited. The specific data values, controller type and projectiles would be declared and initialized within the newShip.
To implement this ship within the overall game structure, the only other classes that would require change would be the load area of the GameState class and the World class where the enemy would exist within the level. The GameState class loads all needed sprite resources and their corresponding type into a GameObjectFactory which is called by the World when creating a new GameObject.
What I give up with the simplicity is some flexibility, the director/world class is tightly coupled to the key game objects but as said, it only requires simple modification when adding a new key game element.
Downloads:
Game requires Windows XP or Vista.
A video card with Shader Model 2.0 is recommended.
XNA 3.0 Redistributable and .NET Framework 3.5 are required. They will be installed automatically if not found.
See README for controls and install instructions.
![]()
Code Snippets:
This class is used by the charge energies, kamikazes and homing rockets for movement. Each movable object within Fusion has a controller interface which can be set to different sub-types depending on the function. Designing this interface allowed much reuse as well as flexibillity for changing the enemies' movement dynamically.
class AttractToObjectController : IController
{
GameObject parent;
GameObject target;
float turnSpeed;
float turnToTargetRotation = 1f;
float desiredAngle;
float accellSpeed;
bool locked;
bool hasTargeted;/// <summary>
/// the constructor
/// </summary>
/// <param name="parent">parent object</param>
/// <param name="target">target--usually playership</param>
/// <param name="turnSpeed">rate of rotation</param>
/// <param name="accellSpeed">rate of movement</param>
/// <param name="locked">true -lock on target, false move to targets location at a given time</param>
public AttractToObjectController(GameObject parent, GameObject target, float turnSpeed,float accellSpeed, bool locked)
{
this.parent = parent;
this.target = target;
this.turnSpeed = turnSpeed;
this.accellSpeed = accellSpeed;
this.locked = locked;}
public void Update(GameTime gameTime)
{
parent.isActive = true;
if (locked)
{
TurnToFace(target.worldPosition, turnSpeed);
}
else if (!hasTargeted)
{
TurnToFace(target.worldPosition, turnSpeed);
hasTargeted = true;
}float distanceFromTarget = Vector2.Distance(target.worldPosition, parent.worldPosition);
accellSpeed += .01f;
if (distanceFromTarget < 100)
accellSpeed += .05f;Vector2 heading = new Vector2(
(float)Math.Cos(turnToTargetRotation), (float)Math.Sin(turnToTargetRotation));
parent.Rotation = turnToTargetRotation;
parent.worldPosition += heading * accellSpeed;
}
/// <summary>
/// Turns the gameObject towards a vector(target's position") at the given speed.
/// </summary>
public void TurnToFace(Vector2 target, float turnSpeed)
{
float x = target.X - parent.worldPosition.X;
float y = target.Y - parent.worldPosition.Y;desiredAngle = (float)Math.Atan2(y, x);
float difference = WrapAngle(desiredAngle - turnToTargetRotation);difference = MathHelper.Clamp(difference, -turnSpeed, turnSpeed);
turnToTargetRotation = WrapAngle(turnToTargetRotation + difference);
}/// Returns the angle expressed in radians between -Pi and Pi.
/// <param name="radians">the angle to wrap, in radians.</param>
/// <returns>the input value expressed in radians from -Pi to Pi.</returns>
/// </summary>
float WrapAngle(float radians)
{
while (radians < -MathHelper.Pi)
{
radians += MathHelper.TwoPi;
}
while (radians > MathHelper.Pi)
{
radians -= MathHelper.TwoPi;
}
return radians;
}}
This class is the overall collision visitor for enemies. I decided to move specific collision handling for each abstract type to its own visitor. The specific enemies, such as a boss would have its own handling implemented in its Die() method. This visitor allows me perform a simple, yet somewhat inefficient (n^2) approach to collision detection and handling. I can loop through a list of game objects and perform statements similar to gameObject1.collideWith(gameObject2). The collideWith method would call gameObject2.visit(this) and execute the corresponding visitor depending on the the specific type of gameObject1 or the "this" object. Performance does not suffer with this approach, thus I felt no need for any optimization.
class EnemyVisitor : Visitor
{
Enemy enemy;
public EnemyVisitor(Enemy enemy)
{
this.enemy = enemy;
}
public override void Visit(PlayerShip player)
{
if (enemy.isCollidable)
{
enemy.Die();
}
}public override void Visit(Projectile shot)
{
if (enemy.isCollidable)
{
enemy.HitPoints -= (int)(shot.Damage);
enemy.isHitActive = true;
if (enemy.HitPoints <= 0)
{
enemy.Die();
}
}
}
}





