Skip to content

Instantly share code, notes, and snippets.

@bartosz-witkowski
Created October 16, 2014 19:51
Show Gist options
  • Save bartosz-witkowski/eb359d51852015a1f281 to your computer and use it in GitHub Desktop.
Save bartosz-witkowski/eb359d51852015a1f281 to your computer and use it in GitHub Desktop.
"Entity component system" with type classes
case class Map(
// in real code use something that has better copy characteristics like some tree
walls: List[Wall],
boundaries: MapBoundaries)
case class World(
player: PlayerCharacter,
map: Map,
enemies: List[Enemy])
case class BoundingBox(x: Int, y: Int, width: Int, height: Int)
trait HasBoundingBox[T] {
def bbox(t: T): BoundingBox
}
trait Movable[T] {
def move(t: T, dx: Int, dy: Int): T
}
trait PlayerOwned[T] {
def react(t: T, input: PlayerInput): T
}
trait Renderable[T] {
def render(t: T): Unit // or IO[Unit] if you want to
}
trait AiControlled[T] {
def takeAction(t: T): T
}
case class PlayerCharacter(x: Int, y: Int)
object PlayerCharacter extends PlayerCharacterInstances
trait PlayerCharacterInstances {
val PlayerSize = 10
implicit val instance = new HasBoundingBox[Player] with Movable[Player] with PlayerOwned[Player] with Renderable[Player] {
override def bbox(player: Player): BoundingBox =
BoundingBox(player.x - (PlayerSize / 2), player.y - (PlayerSize/ 2), PlayerSize, PlayerSize)
override def move(player: Player, dx: Int, dy: Int): Player = {
// for more complicated objects and logics look at lenses / monocle project
Player.copy(x = x + dx, y = y + dy)
}
override def render(player: Player): Unit = {
println(s"rendering: ${player}")
}
override def react(t: T, input: PlayerInput)
}
}
case class Wall(x1: Int, y1: Int, x2: Int, y2: Int)
object Wall extends WallInstances
trait WallInstances {
implicit val instance = new HasBoundingBox[Wall] with Movable[Wall] with Renderable[Wall] {
// blah
}
}
case class MapBoundaries(path: Path)
object MapBoundaries extends MapBoundariesInstances
trait MapBoundariesInstances {
implicit val instance = new HasBoundingBox[Wall] {
// blah
}
}
case class Enemy(x: Int, y: Int, hp: Int)
object Enemy extends EnemyInstances
trait EnemyInstances {
implicit val instance = new HasBoundingBox[Enemy] with Movable[Enemy] with AiControlled[Enemy] with Renderable[Enemy] {
// blah
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment