imj-game-hamazed-0.1.0.2: src/Imj/Game/Hamazed/World/Create.hs
{-# 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
-- ^ Tells where to draw the 'World' from
-> Size
-- ^ The dimensions
-> WallDistribution
-- ^ How the 'Wall's should be constructed
-> [Int]
-- ^ The numbers for which we will create 'Number's.
-> Int
-- ^ Ammunition : how many laser shots are available.
-> 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
-- | Updates 'PosSpeed' of a movable item, according to 'Space'.
updateMovableItem :: Space
-- ^ The surrounding 'Space' will be taken into account for collisions.
-> PosSpeed
-- ^ The current position and speed of the moving item.
-> PosSpeed
-- ^ The updated position and speed.
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
-- Precollision position is the same as the previous position, we try to move
doBallMotionUntilCollision space newPs
NoCollision -> doBallMotion newPs
-- if we ever change this, we should chek other places where we use sumPosSpeed
-- to use this function instead
doBallMotion :: PosSpeed -> PosSpeed
doBallMotion (PosSpeed pos speed) =
PosSpeed (sumPosSpeed pos speed) speed
-- | Changes the position until a collision is found.
-- Doesn't change the 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