Magmageddon
Development
I implemented the project together with my fellow students Janick Bernet and Dominik Käser for ?Game Programming Laboratory? course at ETH during the spring semester 2009.
Detailed Description
Magmageddon is a multiplayer action game targeting the Xbox 360. It plays inside the crater of an active volcano. There are stone pillars sticking out of the lava and floating islands move around the area. Each player controls a robot and has different means to move between the floating islands. The game?s goal is to kill the enemy players by either pushing them into the lava or killing them using some special ability. In addition there are power ups which can be used to regain health, energy or lost lives. The player who survives the longest wins the game.
Technical Details
- Additional Developers: Janick Bernet, Dominik Käser
- Programming Language: C#
- Development Environment: Microsoft Visual Studio.NET 2005 and XNA Game Studio
- Project Size (C# Code): 253 files, 20'733 code lines, 1'673 comment lines, 3'820 blank lines, 913 KiB code
- Project Size (.fx Code): 36 files, 3'087 code lines, 778 comment lines, 1'118 blank lines, 146 KiB code
- Project Duration: One Semester (14 Weeks)
- Technology used: XNA, Animation Component Library, Xbox 360
Feature List
- Robots fighting in death match mode
- Different maps, with their specific visual and playing style
- Three attack types: ice spike (long range), flamethrower (medium range) and pushing (short range)
- Three means to navigate between islands: jump (short range), repulsion (long range) and jetpack (backup)
- Full utilization of the Xbox?s three cores through parallelization
- A sophisticated lava rendering effect
- Postprocessing (HDR, Glow, etc.)
- GPU based particle systems
Challenges
The by far most challenging aspect of this project was to change the original game idea into a game that is fun to play. We discussed in the beginning this idea with an ever changing three dimensional battle arena. It was clear at every stage of the project that the biggest issue is to move in this arena which is very hard without support from the game. So we implemented a ton of features which we thought could be fun. In the end we extracted with a lot of testing the small subset of those features that was needed to make the game fun to play.
Screenshots - Current Release
Videos - Current Release
Code Sample
This code sample shows the update routine of the collision manager.
public void Update(SimulationTime simTime)
{
Game.Instance.SimulationThread.Profiler.BeginSection("collision_update");
//long t1 = System.DateTime.Now.Ticks;
Game.Instance.SimulationThread.Profiler.BeginSection("collision_detection");
testList.BeginCollisionDetection();
//long t2 = System.DateTime.Now.Ticks;
foreach (CollisionThread t in threads)
{
t.Start();
}
//long t3 = System.DateTime.Now.Ticks;
foreach (CollisionThread t in threads)
{
t.Join();
}
//long t4 = System.DateTime.Now.Ticks;
testList.EndCollisionDetection();
Game.Instance.SimulationThread.Profiler.EndSection("collision_detection");
//long t5 = System.DateTime.Now.Ticks;
Game.Instance.SimulationThread.Profiler.BeginSection("collision_response");
foreach (CollisionThread t in threads)
{
//System.Console.WriteLine("collisions: " + t.ContactCount);
for (int i = 0; i < t.ContactCount; ++i)
{
Contact contact = t.GetContact(i);
CollisionProperty propertyA = contact.EntityA.HasProperty("collision") ?
contact.EntityA.GetProperty<CollisionProperty>("collision") : null;
CollisionProperty propertyB = contact.EntityB.HasProperty("collision") ?
contact.EntityB.GetProperty<CollisionProperty>("collision") : null;
if (propertyA != null && propertyB != null)
{
propertyA.FireContact(simTime, contact);
contact.Reverse();
propertyB.FireContact(simTime, contact);
}
else
{
if (propertyA == null && propertyB == null)
{
throw new System.Exception(string.Format(
"someone has illegaly removed" +
"the collision property from entity {0} and {1}!",
contact.EntityA.Name, contact.EntityB.Name
));
}
else
{
throw new System.Exception(string.Format(
"someone has illegaly removed" +
"the collision property from entity {0}!",
propertyA == null ? contact.EntityA.Name : contact.EntityB.Name
));
}
}
}
}
Game.Instance.SimulationThread.Profiler.EndSection("collision_response");
//long t6 = System.DateTime.Now.Ticks;
//long dt1 = t2 - t1;
//long dt2 = t3 - t2;
//long dt3 = t4 - t3;
//long dt4 = t5 - t4;
//long dt5 = t6 - t5;
//double ddt1 = (double)dt1 / 10000.0;
//double ddt2 = (double)dt2 / 10000.0;
//double ddt3 = (double)dt3 / 10000.0;
//double ddt4 = (double)dt4 / 10000.0;
//double ddt5 = (double)dt5 / 10000.0;
//System.Console.WriteLine("collision detection timing: ");
//System.Console.WriteLine(" dt1: {0:G}", ddt1);
//System.Console.WriteLine(" dt2: {0:G}", ddt2);
//System.Console.WriteLine(" dt3: {0:G}", ddt3);
//System.Console.WriteLine(" dt4: {0:G}", ddt4);
//System.Console.WriteLine(" dt5: {0:G} {1}", ddt5, ddt5>10.0?"************":"");
Game.Instance.SimulationThread.Profiler.EndSection("collision_update");
}
Additional Material / Downloads
Related Links