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