layers-game-0.3: src/GameData/Boundary.hs
module GameData.Boundary where
#include "Utils.cpp"
import qualified Data.List as L
import qualified GameData.Entity as E
import qualified Entity.Bound as EB
import qualified GameData.Player as PL
import qualified GameData.Animation as A
import qualified Gamgine.Math.Box as B
import qualified Gamgine.Math.Vect as V
import Gamgine.Math.Vect
import qualified Gamgine.Math.BoxTree as BT
import qualified Entity.Bound as EB
IMPORT_LENS_AS_LE
-- | the boundary of the whole level
data Boundary = Boundary {box :: B.Box} deriving Show
LENS(box)
newBoundary :: [E.Entity] -> Boundary
newBoundary entities = Boundary boundary
where
boundary = B.Box (V.v3 0 0 0) $ maxArea + V.v3 minBorderDist minBorderDist 0
B.Box _ maxArea = entitiesArea entities
minBorderDist = (max (fst PL.playerSize) (snd PL.playerSize)) * 6
boundaryArea :: Boundary -> V.Vect
boundaryArea (Boundary (B.Box minPt maxPt)) = maxPt - minPt
keepInside :: E.Entity -> Boundary -> E.Entity
player@E.Player {} `keepInside` Boundary bBound@(B.Box minBd@(_:.minY:._) maxBd)
| pBound `B.inside` bBound = player
| otherwise = player {E.playerPosition = pos',
E.playerVelocity = velo',
E.playerOnBottom = onBottom}
where
pBound = (BT.asBox $ E.playerBound player) `B.moveBy` playPos
pos' = V.minVec (V.maxVec minBd playPos) maxPos
velo' = V.v3 vx vy' vz
vy' | posY > maxY = 0
| posY < minY = 0
| otherwise = vy
onBottom | posY < minY = True
| otherwise = E.playerOnBottom player
maxPos@(_:.maxY:._) = maxBd - V.v3 (fst PL.playerSize) (snd PL.playerSize) 0
playPos@(_:.posY:._) = E.playerPosition player
(vx:.vy:.vz:.()) = E.playerVelocity player
keepInside entity _ = entity
entitiesArea :: [E.Entity] -> B.Box
entitiesArea entities = B.bound $ L.map bound entities
where
bound E.Platform {E.platformPosition = Right ani, E.platformBound = bound} = pathBound
where
pathBound = B.bound $ L.map (bound `B.moveBy`) $ A.path ani
bound e = BT.asBox $ EB.bound e