package MessagingInScala object GameMessageType extends Enumeration { type GameMessageType = Value val SetPosition = Value val GetPosition = Value } import GameMessageType._ class Vector3(var x: Float, var y: Float, var z: Float) abstract class GameMessage (val destinationID: Int) { def messageType: GameMessageType } abstract class PositionMessage (destinationID: Int, var x: Float, var y: Float, var z: Float) extends GameMessage(destinationID) { } class MsgSetPosition(destinationID: Int, x: Float, y: Float, z: Float) extends PositionMessage(destinationID, x, y, z) { override val messageType = SetPosition } object MsgSetPosition { def Apply(destinationID: Int, x: Float, y: Float, z: Float) = new MsgSetPosition(destinationID, x, y, z) } class MsgGetPosition(destinationID: Int) extends PositionMessage(destinationID, 0.0f, 0.0f, 0.0f) { val messageType = GetPosition } object MsgGetPosition { def Apply(destinationID: Int) = new MsgGetPosition(destinationID) } abstract class BaseComponent { def SendMessage(message: GameMessage) = false } class RenderComponent extends BaseComponent { override def SendMessage(message: GameMessage): Boolean = { message.messageType match { case GameMessageType.SetPosition => { // Update render mesh position println("RenderComponent received SetPosition") true // Return value } case _ => super.SendMessage(message) } } } class Entity(ID: Int) { private var Components: List[BaseComponent] = List() var position: Vector3 = new Vector3(0.0f, 0.0f, 0.0f) val uniqueID: Int = ID def AddComponent(component: BaseComponent) { Components = component :: Components } def SendMessage(message: GameMessage): Boolean = { message.messageType match { case GameMessageType.SetPosition => { println("Entity received SetPosition") var msgSetPos: MsgSetPosition = message.asInstanceOf[MsgSetPosition] position.x = msgSetPos.x position.y = msgSetPos.y position.z = msgSetPos.z PassMessageToComponents(message) // This is also the return value } case GameMessageType.GetPosition => { println("Entity received GetPosition") var msgGetPos: MsgGetPosition = message.asInstanceOf[MsgGetPosition] msgGetPos.x = position.x msgGetPos.y = position.y msgGetPos.z = position.z PassMessageToComponents(message) // This is also the return value } case _ => PassMessageToComponents(message) // This is also the return value } } def PassMessageToComponents(message: GameMessage): Boolean = { var messageHandled = false Components.foreach(c => { messageHandled |= c.SendMessage(message) }) messageHandled } } object Entity { var nextUUID: Int = 0 def apply() = new Entity(nextUUID + 1) } class SceneManager { // You don't need to type the entire HashMap path like this, I'm // doing this so the reader understands this is not a Java HashMap var entities: Map[Int, Entity] = Map.empty[Int, Entity] def SendMessage(message: GameMessage): Boolean = { if ( entities.contains(message.destinationID) ) { entities(message.destinationID).SendMessage(message) } else { false } } def CreateEntity(): Entity = { val newEntity: Entity = Entity() entities += newEntity.uniqueID -> newEntity newEntity } } object Main extends App { val sceneMgr: SceneManager = new SceneManager val testEntity = sceneMgr.CreateEntity() val testRenderComp = new RenderComponent testEntity.AddComponent(testRenderComp) val msgSetPos: MsgSetPosition = new MsgSetPosition(testEntity.uniqueID, 1.0f, 2.0f, 3.0f) sceneMgr.SendMessage(msgSetPos) println("Position set to (1, 2, 3) on entity with ID " + testEntity.uniqueID) println("Retreiving position from object with ID: " + testEntity.uniqueID) val msgGetPos: MsgGetPosition = new MsgGetPosition(testEntity.uniqueID) sceneMgr.SendMessage(msgGetPos) println("X: " + msgGetPos.x) println("Y: " + msgGetPos.y) println("Z: " + msgGetPos.z) }
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, now in Scala
In my previous post I discussed game engine architecture, object<->component hierarchy, etc. Here's the sample architecture as the last post, but instead of C++ this version is written in Scala. One thing worth noting, we get identical functionality in this Scala example, with 35% less code!
Labels:
game architecture,
game engine,
messaging,
scala
Subscribe to:
Post Comments (Atom)
Really nice, thanks for sharing.
ReplyDelete