I am currently developing a game in Scala where I have a number of entities (e.g. GunBattery, Squadron, EnemyShip, EnemyFighter) that all inherit from a GameEntity class. Ga
A standard mechanism for this (not scala-specific) is a chain of handlers. For example:
trait Handler[Msg] {
handle(msg: Msg)
}
Then your entities just need to manage a list of handlers:
abstract class AbstractEntity {
def handlers: List[Handler]
def receive(msg: Msg) { handlers foreach handle }
}
Then your entities can declare the handlers inline, as follows:
class Tank {
lazy val handlers = List(
new Handler {
def handle(msg: Msg) = msg match {
case ied: IedMsg => //handle
case _ => //no-op
}
},
new Handler {
def handle(msg: Msg) = msg match {
case ef: EngineFailureMsg => //handle
case _ => //no-op
}
}
)
Of course the disadvantage here is that you lose readability, and you still have to remember the boilerplate which is a no-op catch-all case for each handler.
Personally I would stick with the duplication. What you have at the moment looks a lot like treating each entity as if it is an Actor
. For example:
class Tank extends Entity with Actor {
def act() {
loop {
react {
case ied: IedMsg => //handle
case ied: EngineFailureMsg => //handle
case _ => //no-op
}
}
}
}
At least here you get into the habit of adding a case
statement within the react loop. This can call another method in your actor class which takes the appropriate action. Of course, the benefit of this is that you take advantage of the concurrency model provided by the actor paradigm. You end up with a loop which looks like this:
react {
case ied: IedMsg => _explosion(ied)
case efm: EngineFailureMsg => _engineFailure(efm)
case _ =>
}
You might want to look at akka, which offers a more performant actor system with more configurable behaviour and more concurrency primitives (STM, agents, transactors etc)