Original Post
I have finally realized that I will not have time to finish my C#/MDX game I started almost two years ago in the next few years, therefore I have decided to release it as-is (thought it is very playable as it is now). The game offers neat physics and a separate game and game engine, both written in C#/MDX. Feel free to play around with the code; it should compile out of the box if you have Microsoft Visual C# 2005 Express Edition and MDX/.NET 2.0 SDK:s installed. The engine is based on superpig's Kernel architecture in the Enginyity series. My current code uses a naive static class approach, but I still think the code might be useful for some. Get it from http://www.chromecode.com/downloads or directly: spatra_2_unfinnished_game.zip
Here a sample source file (Kernel.cs) Have fun! [Edited by - Enselic on October 31, 2006 5:50:02 PM]
// +---------------------------------------------------------------------------+
//
// Copyright © 2006 Martin Nordholts. All rights reserved.
// Website: http://www.chromecode.com
//
//
// File: Kernel.cs
// Created: 2005-10-23
//
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// +---------------------------------------------------------------------------+
using System;
using System.Collections.Generic;
namespace Chrocodile
{
/// <remarks>
/// The Kernel is the heart of the engine.
/// As long as the taskList contains tasks, it will continue to
/// call Update() on these tasks. It automaticly removes tasks
/// which have the CanKill property set to true.
/// </remarks>
public static class Kernel
{
/// <summary>
/// Kicks off the main loop,
/// which is run until there are no tasks left to Update()
/// </summary>
static public void Execute()
{
while (taskList.Count > 0) {
for (LinkedListNode<AbstractTask> taskListNode = taskList.First; taskListNode != null; taskListNode = taskListNode.Next) {
if (!taskListNode.Value.CanKill) {
taskListNode.Value.Update();
}
}
for (LinkedListNode<AbstractTask> taskListNode = taskList.First; taskListNode != null; taskListNode = taskListNode.Next) {
if (taskListNode.Value.CanKill) {
taskListNode.Value.Stop();
taskList.Remove(taskListNode);
}
}
}
}
/// <summary>
/// Adds a given task to the Kernel's taskList. Before a task is added,
/// its Start()-method is called.
/// </summary>
/// <param name="taskToAdd">Task to add</param>
/// <returns>Returns true if the task could be added to the taskList, false otherwise</returns>
static public bool AddTask(AbstractTask taskToAdd)
{
if (!taskToAdd.Start())
return false;
LinkedListNode<AbstractTask> node;
for (node = taskList.First; node != null; node = node.Next) {
AbstractTask task = node.Value;
if (taskToAdd.Priority < task.Priority) {
taskList.AddBefore(node, taskToAdd);
return true;
}
}
taskList.AddLast(taskToAdd);
return true;
}
/// <summary>
/// Suspends a given task. When a task is suspended, its
/// OnSuspend()-method is called.
/// </summary>
/// <param name="taskToSuspend">Task to suspend</param>
static public void SuspendTask(AbstractTask taskToSuspend)
{
if (taskList.Contains(taskToSuspend)) {
taskToSuspend.OnSuspend();
taskList.Remove(taskToSuspend);
suspendedTaskList.AddLast(taskToSuspend);
}
}
/// <summary>
/// Resumes a given task (which has been suspended).
/// When a task is resumed, its OnResume()-method is called.
/// </summary>
/// <param name="taskToResume">Task to resume</param>
static public void ResumeTask(AbstractTask taskToResume)
{
if (suspendedTaskList.Contains(taskToResume)) {
taskToResume.OnResume();
suspendedTaskList.Remove(taskToResume);
LinkedListNode<AbstractTask> node;
for (node = taskList.First; node != null; node = node.Next) {
AbstractTask task = node.Value;
if (taskToResume.Priority < task.Priority) {
taskList.AddBefore(node, taskToResume);
return;
}
}
taskList.AddLast(taskToResume);
return;
}
}
/// <summary>
/// Removes a given task from the taskList
/// </summary>
/// <param name="taskToKill">Task to remove</param>
static public void KillTask(AbstractTask taskToKill)
{
if (taskList.Contains(taskToKill)) {
taskToKill.CanKill = true;
}
}
/// <summary>
/// Removes all tasks form the taskList. This method is typically
/// called whenever the game should exit.
/// </summary>
static public void KillAllTasks()
{
foreach (AbstractTask task in taskList) {
task.CanKill = true;
}
}
static private LinkedList<AbstractTask> taskList = new LinkedList<AbstractTask>();
static private LinkedList<AbstractTask> suspendedTaskList = new LinkedList<AbstractTask>();
}
}