{-# LANGUAGE PatternGuards #-} import Game import Level import MainLoop import Render import Player import CPUPlayer import DefaultPlayer import HWiidPlayer import Simulation import Tank import Vector import GLDriver import GLX import Control.Monad.State import Data.Maybe import qualified Data.Map as M import qualified Data.Set as S import Data.Time main :: IO () main = do let theLevel = testLevel --humanPlayer <- newHWiidPlayer let humanPlayer = DefaultPlayer S.empty 0 0 False gl <- initGL $ glxDriver (levelWidth theLevel) (levelHeight theLevel) when (initialized gl) $ do currentTime <- getCurrentTime let gamestate = GameState {level = theLevel, tanks = [ Tank (Vertex 7.0 4.0) zeroV zeroV 1.5 (270*pi/180) False 3 1 5 1 , Tank (Vertex 4.0 4.0) zeroV zeroV 1.5 (270*pi/180) False 3 1 5 1 , Tank (Vertex 10.0 4.0) zeroV zeroV 1.5 (270*pi/180) False 3 1 5 1 ], bullets = []} mainstate = MainState {run = True, driver = SomeDriver gl, time = currentTime, players = [ SomePlayer humanPlayer , SomePlayer $ CPUPlayer $ fromAngle $ -pi/2 , SomePlayer $ CPUPlayer $ fromAngle $ pi/2 ], textures = M.empty, models = M.empty, gameState = gamestate} runMain mainstate $ do setup mainLoop deinitGL gl minFrameTime :: NominalDiffTime minFrameTime = 0.02 mainLoop :: Main () mainLoop = do gl <- gets driver t <- gets time handleEvents render liftIO $ swapBuffers gl rtime <- liftIO getCurrentTime let drender = diffUTCTime rtime t when (drender < minFrameTime) $ liftIO $ usleep gl $ truncate $ 1e6*(minFrameTime - drender) currenttime <- liftIO getCurrentTime let d = round $ 1e2*(diffUTCTime currenttime t) replicateM_ d simulationStep let newtime = addUTCTime ((1e-2)*(fromIntegral d)) t modify $ \state -> state {time = newtime} runnext <- gets run when runnext mainLoop handleEvents :: Main () handleEvents = do (newgl, event) <- gets driver >>= liftIO . nextEvent modify $ \state -> state {driver = newgl} when (isJust event) $ do Main.handleEvent $ fromJust event modify $ \state -> state {players = map (\p -> Player.handleEvent p $ fromJust event) $ players state} handleEvents handleEvent :: SomeEvent -> Main () handleEvent ev | Just QuitEvent <- fromEvent ev = modify $ \state -> state {run = False} | otherwise = return ()