brillo-examples-1.13.3: picture/Styrene/World.hs
{-# LANGUAGE PatternGuards #-}
-- The world contains a map of all the actors, along with the current
-- quadtree so we can also draw it on the screen.
module World where
import Actor (Actor (..), Index, actorIx, actorSetIndex)
import Config (
beadBoxSize,
beadCountX,
beadCountY,
beadRadius,
boxSize,
treeMaxDepth,
treeSize,
)
import QuadTree (QuadTree, treeInsert, treeZero)
import Data.Map (Map)
import Data.Map qualified as Map
-- The world ------------------------------------------------------------------
data World
= World
(Map Index Actor) -- actors
(QuadTree Actor) -- tree
-- | The initial world
worldInit :: World
worldInit =
World actorMapInit treeInit
actorMapInit :: Map Index Actor
actorMapInit =
Map.fromList $
map
(\a -> (actorIx a, a))
(walls ++ beads)
treeInit :: QuadTree a
treeInit = treeZero treeSize
-- Walls ------------------
walls :: [Actor]
walls = zipWith actorSetIndex (box ++ splitter) [10000 ..]
box :: [Actor]
box =
let bs = boxSize
in [ Wall 0 (-bs, -bs) (bs, -bs) -- bot
, Wall 0 (-bs, bs) (bs, bs) -- top
, Wall 0 (-bs, -bs) (-bs, bs) -- left
, Wall 0 (bs, -bs) (bs, bs) -- right
]
splitter :: [Actor]
splitter =
[ Wall 0 (-15, -100) (-200, 0)
, Wall 0 (15, -100) (200, 0)
]
-- Beads ------------------
beads :: [Actor]
beads =
let
-- beads start off with their index just set to 0
beads_raw =
[ Bead 0 0 beadRadius (beadPos ix iy) (0, 0)
| ix <- [0 .. beadCountX - 1]
, iy <- [0 .. beadCountY - 1]
]
in
-- set the unique index on the beads before returning them
zipWith actorSetIndex beads_raw [0 ..]
beadPos :: Float -> Float -> (Float, Float)
beadPos ix iy =
( (ix * beadBoxSize) - (beadBoxSize * beadCountX / 2)
, iy * beadBoxSize
)
-- QuadTree -------------------------------------------------------------------
-- | insert an actor into the tree
insertActor :: Actor -> QuadTree Actor -> QuadTree Actor
insertActor actor tree
-- insert a bead into the tree
| bead@(Bead _ix _ radius (x, y) _vel) <- actor =
let
-- the bottom left and top right of the bead's bounding box.
p0 = (x - radius, y - radius)
p1 = (x + radius, y + radius)
in
treeInsert treeMaxDepth 0 p0 p1 bead tree
| wall@(Wall _ix (x0, y0) (x1, y1)) <- actor =
let
-- the bottom left and top right of the wall's bounding box.
p0 = (min x0 x1, min y0 y1)
p1 = (max x0 x1, max y0 y1)
in
treeInsert treeMaxDepth 0 p0 p1 wall tree