What’s wrong with OOP for games?
von Karma
Who cares if a foolish fool like you doesn’t like it? OOP is the natural way to model a game world.
Pure Ideology
Natural?
Thanks Lakitu. Plumber, please reduce your HP by 1
Hey Bill, you just
hit that plumber!
Of-a course Bill, that’s-a my job after all!
We want…
Glossy MVC
deltaTime
von Karma
Tsk, tsk, tsk. A design pattern? You’re not running back to OOP already now are you?
Glossy MVC
Bristol CSS Game Jam 2018
What does gloss help you with?
von Karma
What is this "Ace Attorney"? Just another simple game, no doubt. How convenient that none of these games have complex interactions between different… objects.
What doesn’t gloss help you with?
Solution: ECS
von Karma
Another design pattern? You are becoming predictable…
Defining Basic Components
newtype Velocity = Vel (Float, Float)
instance Component Velocity where type Storage Velocity = Map Velocity
newtype Position = Pos (Float, Float)
instance Component Position where type Storage Position = Map Position
~Map Entity Velocity
{-# language TypeFamilies #-}
~Map Entity Position
Creating new entities
createEntities :: System' ()
createEntities = do
newEntity_ (Pos (0,0), Vel (10,10))
newEntity_ (Pos (50,50), Vel (-10,-10))
von Karma
Set'? System'? I know what you Haskellers are like. Those aren’t the real types, are they? What are you hiding?
newEntity_
:: Set' component
=> component -> System' ()
newEntity_
:: (MonadIO m, Set world m component, Get world m EntityCounter)
=> component -> SystemT world m ()
Defining basic systems
stepPos :: Float -> System' ()
stepPos dt
= cmap (\(Pos (x,y), Vel (vX, vY))
-> Pos (x + vX * dt, y + vY * dt))
cmap
:: (Get' cx, Members' cx, Set' cy)
=> (cx -> cy) -> System' ()
Gloss integration: Model
Generates:
{-# language TemplateHaskell #-}
import Apecs.Gloss
type System' a = System Model a
Gloss integration: View
view :: System Model Picture
view
= foldDraw (\(Pos (x,y))
-> translate x y (circle 10))
foldDraw
:: (Get' c, Members' c)
=> (c -> Picture) -> System Model Picture
Gloss integration: Controller
inputController :: Event -> System Model ()
inputController event = case event of
EventKey (SpecialKey KeyEsc) Down _ _
-> liftIO exitSuccess
_ -> pure ()
stepPos :: Float -> System Model ()
stepPos dt
= cmap (\(Pos (x,y), Vel (vX, vY))
-> Pos (x + vX * dt, y + vY * dt))
Time step controller
reminder
Gloss integration: Modified play
Gloss integration
Live demo
von Karma
You promised complex interactions, but all I see are circles moving in a straight line. I don’t have time for your stalling, hurry up and show me some real evidence!
Emergent systems: Boids
What a boid brain!
boid = “bird-oid object”
Boids: Separation
source: http://www.red3d.com/cwr/boids/
Boids: Separation
separation :: System' ()
separation = cmapM $ \(Boid, Position p, Velocity v) -> do
collect :: _ => (components -> Maybe a) -> System' [a]
localDistVecs
<- collect
(\(Obstacle, Position p')
-> (p - p') `justIf` (withinRange separationDist p p'))
let dv = separationFactor *^ sumV localDistVecs
pure $ Velocity (v + dv)
cmapM :: (Get' cx, Members' cx, Set' cy) => (cx -> System' cy) -> System' ()
justIf :: a -> Bool -> Maybe a
Boids: Cohesion
source: http://www.red3d.com/cwr/boids/
Boids: Cohesion
cohesion :: System' ()
cohesion = cmapM $ \(Boid, Position p, Velocity v, etyX :: Entity) -> do
localPs <- collect $ \(Boid, Position p', etyY :: Entity)
-> p' `justIf` (withinRange sightRadius p p'
&& etyX /= etyY)
let dv = case localPs of
[] -> 0
_ -> cohesionFactor *^ (mean localPs - p)
pure $ Velocity (v + dv)
Boids: Alignment
source: http://www.red3d.com/cwr/boids/
Boids: Alignment
alignment :: System' ()
alignment = cmapM $ \(Boid, Position p, Velocity v, etyX :: Entity) -> do
localVs <- collect $ \(Boid, Position p', Velocity v', etyY :: Entity)
-> v' `justIf` (withinRange sightRadius p p'
&& etyX /= etyY)
let dv = case localVs of
[] -> 0
_ -> alignmentFactor *^ (mean localVs - v)
pure $ Velocity (v + dv)
von Karma
Hmph. I suppose your case isn’t completely worthless. Just be glad this is not a real court. If it were, I would not be letting you off so easy.
Boidemic
Live demo
Conclusion
Questions?
https://plrg-bristol.github.io/