{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Imj.Game.Hamazed.World.Create
( mkWorld
, updateMovableItem
) where
import Imj.Prelude
import Control.Monad.IO.Class(MonadIO, liftIO)
import Imj.Game.Hamazed.World.Number
import Imj.Game.Hamazed.World.Ship
import Imj.Game.Hamazed.World.Space
import Imj.Game.Hamazed.World.Types
import Imj.Geo.Discrete
import Imj.Physics.Discrete.Collision
import Imj.Timing
mkWorld :: (MonadIO m)
=> InTerminal
-> Size
-> WallDistribution
-> [Int]
-> Int
-> m World
mkWorld e s walltype nums ammo = do
space <- case walltype of
None -> return $ mkEmptySpace s
Deterministic -> return $ mkDeterministicallyFilledSpace s
Random rParams -> liftIO $ mkRandomlyFilledSpace rParams s
t <- liftIO getSystemTime
balls <- mapM (createRandomNumber space) nums
ship@(PosSpeed pos _) <- liftIO $ createShipPos space balls
return $ World balls (BattleShip ship ammo (Just $ addToSystemTime 5 t) (getColliding pos balls)) space [] e
updateMovableItem :: Space
-> PosSpeed
-> PosSpeed
updateMovableItem space ps@(PosSpeed pos _) =
let (newPs@(PosSpeed newPos _), collision) =
mirrorSpeedAndMoveToPrecollisionIfNeeded (`location` space) ps
in case collision of
PreCollision ->
if pos /= newPos
then
newPs
else
doBallMotionUntilCollision space newPs
NoCollision -> doBallMotion newPs
doBallMotion :: PosSpeed -> PosSpeed
doBallMotion (PosSpeed pos speed) =
PosSpeed (sumPosSpeed pos speed) speed
doBallMotionUntilCollision :: Space -> PosSpeed -> PosSpeed
doBallMotionUntilCollision space (PosSpeed pos speed) =
let trajectory = bresenham $ mkSegment pos $ sumPosSpeed pos speed
newPos = maybe (last trajectory) snd $ firstCollision (`location` space) trajectory
in PosSpeed newPos speed
createRandomNumber :: (MonadIO m)
=> Space
-> Int
-> m Number
createRandomNumber space i = do
ps <- liftIO $ createRandomNonCollidingPosSpeed space
return $ Number ps i