using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MessagingInCSharp { class Program { static void Main( string[] args ) { // Create a scene manager SceneManager sceneMgr = new SceneManager(); // Have scene manager create an entity for us, which // automatically puts the object into the scene as well Entity myEntity = sceneMgr.CreateEntity(); // Create a render component RenderComponent renderComp = new RenderComponent(); // Attach render component to the entity we made myEntity.AddComponent(renderComp); // Set 'myEntity' position to (1, 2, 3) MsgSetPosition msgSetPos = new MsgSetPosition(myEntity.uniqueID, 1.0f, 2.0f, 3.0f); sceneMgr.SendMessage(msgSetPos); Console.WriteLine("Position set to (1, 2, 3) on entity with ID: " + myEntity.uniqueID); Console.WriteLine("Retreiving position from entity with ID: " + myEntity.uniqueID); // Get 'myEntity' position to verify it was set properly MsgGetPosition msgGetPos = new MsgGetPosition(myEntity.uniqueID); sceneMgr.SendMessage(msgGetPos); Console.WriteLine("X: " + msgGetPos.x); Console.WriteLine("Y: " + msgGetPos.y); Console.WriteLine("Z: " + msgGetPos.z); } } public enum MessageType { SetPosition, GetPosition } public class Vector3 { public float x = 0.0f; public float y = 0.0f; public float z = 0.0f; } public class BaseMessage { public int destEntityID; public MessageType messageType; protected BaseMessage( int destinationEntityID, MessageType messageType ) { this.destEntityID = destinationEntityID; this.messageType = messageType; } } public class PositionMessage : BaseMessage { public float x; public float y; public float z; protected PositionMessage( int destinationEntityID, MessageType messageType, float X = 0.0f, float Y = 0.0f, float Z = 0.0f) : base(destinationEntityID, messageType) { this.x = X; this.y = Y; this.z = Z; } } public class MsgSetPosition : PositionMessage { public MsgSetPosition( int destinationEntityID, float X, float Y, float Z ) : base(destinationEntityID, MessageType.SetPosition, X, Y, Z) {} } public class MsgGetPosition : PositionMessage { public MsgGetPosition( int destinationEntityID) : base(destinationEntityID, MessageType.GetPosition, 0.0f, 0.0f, 0.0f) {} } public abstract class BaseComponent { public virtual bool SendMessage( BaseMessage msg ) { return false; } } public class RenderComponent : BaseComponent { public override bool SendMessage( BaseMessage msg ) { // Entity has a switch for any messages it cares about switch (msg.messageType) { case MessageType.SetPosition: { // Update render mesh position/translation Console.WriteLine("RenderComponent handling SetPosition"); } break; default: return base.SendMessage(msg); } return true; } } public class Entity { public int uniqueID; public int UniqueID { get { return this.uniqueID; } set { this.uniqueID = value; } } private Vector3 position = new Vector3(); private List<BaseComponent> components = new List<BaseComponent>(); public Entity( int uniqueID ) { this.uniqueID = uniqueID; } public void AddComponent( BaseComponent component ) { this.components.Add(component); } public bool SendMessage( BaseMessage msg ) { bool messageHandled = false; // Entity has a switch for any messages it cares about switch (msg.messageType) { case MessageType.SetPosition: { MsgSetPosition msgSetPos = msg as MsgSetPosition; position.x = msgSetPos.x; position.y = msgSetPos.y; position.z = msgSetPos.z; messageHandled = true; Console.WriteLine("Entity handled SetPosition"); } break; case MessageType.GetPosition: { MsgGetPosition msgGetPos = msg as MsgGetPosition; msgGetPos.x = position.x; msgGetPos.y = position.y; msgGetPos.z = position.z; messageHandled = true; Console.WriteLine("Entity handled GetPosition"); } break; default: return PassMessageToComponents(msg); } // If the entity didn't handle the message but the component // did, we return true to signify it was handled by something. messageHandled |= PassMessageToComponents(msg); return messageHandled; } private bool PassMessageToComponents( BaseMessage msg ) { bool messageHandled = false; this.components.ForEach(c => messageHandled |= c.SendMessage(msg) ); return messageHandled; } } public class SceneManager { private Dictionary<int, Entity> entities = new Dictionary<int,Entity>(); private static int nextEntityID = 0; // Returns true if the entity or any components handled the message public bool SendMessage( BaseMessage msg ) { // We look for the entity in the scene by its ID Entity entity; if ( entities.TryGetValue(msg.destEntityID, out entity) ) { // Entity was found, so send it the message return entity.SendMessage(msg); } // Entity with the specified ID wasn't found return false; } public Entity CreateEntity() { Entity newEntity = new Entity(SceneManager.nextEntityID++); entities.Add(newEntity.UniqueID, newEntity); return newEntity; } } }
A blog by a professional game developer, about game programming and development. My posts will range in comments from beginners to game development to those at a more advanced level.
Saturday, February 11, 2012
Game Engine Architecture, C#
Here's the same architecture as my last two posts, but this time in C# (the last two were in Scala and C++).
Labels:
C#,
game architecture,
game engine,
messaging
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment