summaryrefslogtreecommitdiffstats
path: root/HTanks.hs
diff options
context:
space:
mode:
Diffstat (limited to 'HTanks.hs')
-rw-r--r--HTanks.hs127
1 files changed, 67 insertions, 60 deletions
diff --git a/HTanks.hs b/HTanks.hs
index 22b8309..871b455 100644
--- a/HTanks.hs
+++ b/HTanks.hs
@@ -4,6 +4,8 @@ import Game
import Level
import Render
import Tank
+import Player
+import DefaultPlayer
import GLDriver
import GLX
@@ -22,7 +24,7 @@ data MainState = MainState
{ run :: !Bool
, driver :: !SomeDriver
, time :: !UTCTime
- , keyset :: !(S.Set Key)
+ , players :: ![SomePlayer]
}
newtype MainT m a = MainT (StateT MainState m a)
@@ -40,7 +42,7 @@ main = do
when (initialized gl) $ do
currentTime <- getCurrentTime
- let mainState = MainState {run = True, driver = SomeDriver gl, time = currentTime, keyset = S.empty}
+ let mainState = MainState {run = True, driver = SomeDriver gl, time = currentTime, players = [SomePlayer $ DefaultPlayer S.empty]}
gameState = GameState {level = testLevel, tanks = [Tank 0.0 0.0 0 0 2 360 False], textures = M.empty}
runGame gameState $ do
@@ -80,82 +82,87 @@ mainLoop = do
when runnext mainLoop
-playerMovement :: Main (Maybe Micro, Bool)
-playerMovement = do
- keys <- gets keyset
+
+updateAngle :: Micro -> State Tank ()
+updateAngle angle = do
+ oldangle <- gets dir
+ tspeed <- gets turnspeed >>= return . (/1000)
- let x = (if (S.member KeyLeft keys) then (-1) else 0) + (if (S.member KeyRight keys) then 1 else 0)
- y = (if (S.member KeyDown keys) then (-1) else 0) + (if (S.member KeyUp keys) then 1 else 0)
+ let diff = angle - oldangle
+ let diff360 = if (diff > 180)
+ then (diff-360)
+ else if (diff <= -180)
+ then (diff+360)
+ else diff
- if (x /= 0 || y /= 0)
- then return (Just $ fromRational $ round ((atan2 y x)*1000000*180/pi)%1000000, True)
- else return (Nothing, False)
-
-
-simulationStep :: Main ()
-simulationStep = do
- (angle, move) <- playerMovement
+ let (diff180, angle180) = if (diff360 > 90)
+ then (diff360-180, oldangle+180)
+ else if (diff360 <= -90)
+ then (diff360+180, oldangle-180)
+ else (diff360, oldangle)
- when (isJust angle) $ do
- tank <- lift $ gets (head . tanks)
- let oldangle = dir tank
-
- let diff = fromJust angle - oldangle
- let diff360 = if (diff > 180)
- then (diff-360)
- else if (diff <= -180)
- then (diff+360)
- else diff
-
- let (diff180, angle180) = if (diff360 > 90)
- then (diff360-180, oldangle+180)
- else if (diff360 <= -90)
- then (diff360+180, oldangle-180)
- else (diff360, oldangle)
-
- let tspeed = (turnspeed tank)/1000
- let turn = if (diff180 > tspeed)
- then tspeed
- else if (diff180 < -tspeed)
- then (-tspeed)
- else diff180
-
- let newangle = angle180 + turn
-
- let newangle180 = if (newangle > 180)
- then (newangle-360)
- else if (newangle <= -180)
- then (newangle+360)
- else newangle
-
- lift $ modify $ \state -> state {tanks = (tank {dir = newangle180}):(tail . tanks $ state)}
+ let turn = if (diff180 > tspeed)
+ then tspeed
+ else if (diff180 < -tspeed)
+ then (-tspeed)
+ else diff180
+ let newangle = angle180 + turn
+
+ let newangle180 = if (newangle > 180)
+ then (newangle-360)
+ else if (newangle <= -180)
+ then (newangle+360)
+ else newangle
+
+ modify $ \tank -> tank {dir = newangle180}
+
+updateTank :: Maybe Micro -> Bool -> State Tank ()
+updateTank angle move = do
+ when (isJust angle) $
+ updateAngle $ fromJust angle
+
when move $ do
- tank <- lift $ gets (head . tanks)
- let moved = moving tank
+ tdir <- gets dir
+ tspeed <- gets speed
+ moved <- gets moving
- when (isNothing angle || (isJust angle && (dir tank == fromJust angle)) || moved) $ do
- let angle = (fromRational . toRational $ dir tank)*pi/180
- x = (speed tank) * fromRational (round ((cos angle)*1000)%1000000)
- y = (speed tank) * fromRational (round ((sin angle)*1000)%1000000)
+ when (isNothing angle || (isJust angle && (tdir == fromJust angle)) || moved) $ do
+ let anglej = (fromRational . toRational $ tdir)*pi/180
+ x = tspeed * fromRational (round ((cos anglej)*1000)%1000000)
+ y = tspeed * fromRational (round ((sin anglej)*1000)%1000000)
- lift $ modify $ \state -> state {tanks = (tank {posx = x + posx tank, posy = y + posy tank, moving = True}):(tail . tanks $ state)}
+ modify $ \tank -> tank {posx = x + posx tank, posy = y + posy tank, moving = True}
when (not move) $ do
- tank <- lift $ gets (head . tanks)
- lift $ modify $ \state -> state {tanks = (tank {moving = False}):(tail . tanks $ state)}
+ modify $ \tank -> tank {moving = False}
+
+
+simulationStep :: Main ()
+simulationStep = do
+ oldplayers <- gets players
+ oldtanks <- lift $ gets tanks
+
+ let pt = unzip $ map updateTank' $ zip oldplayers oldtanks
+
+ modify $ \state -> state {players = fst pt}
+ lift $ modify $ \state -> state {tanks = snd pt}
+ where
+ updateTank' (player, tank) = let (p, angle, move) = playerMovement player tank
+ t = execState (updateTank angle move) tank
+ in (p, t)
+
handleEvents :: Main ()
handleEvents = do
event <- gets driver >>= liftIO . nextEvent
when (isJust event) $ do
- handleEvent $ fromJust event
+ Main.handleEvent $ fromJust event
+ modify $ \state -> state {players = map (\p -> Player.handleEvent p $ fromJust event) $ players state}
handleEvents
handleEvent :: SomeEvent -> Main ()
handleEvent ev
| Just (ResizeEvent w h) <- fromEvent ev = lift $ resize w h
- | Just (KeyPressEvent key) <- fromEvent ev = modify $ \state -> state {keyset = S.insert key (keyset state)}
- | Just (KeyReleaseEvent key) <- fromEvent ev = modify $ \state -> state {keyset = S.delete key (keyset state)}
| Just QuitEvent <- fromEvent ev = modify $ \state -> state {run = False}
| otherwise = return ()