engine: Accept (event, timestamp) pairs instead of (event, timeElapsed)

The timeElapsed code was incorrect, applying the event retrospectively
rather than for the future.
arun
Arun Raghavan 2015-07-15 18:24:43 +05:30
parent a2e6bca7b2
commit f8bd50a51b
2 changed files with 16 additions and 11 deletions

View File

@ -32,10 +32,13 @@ move timeElapsed (x, y) (Velocity speed dir) = move' dir
move' Up = tail [(x, y') | y' <- [y, y - 1 .. y - dist]] move' Up = tail [(x, y') | y' <- [y, y - 1 .. y - dist]]
move' Down = tail [(x, y') | y' <- [y .. y + dist]] move' Down = tail [(x, y') | y' <- [y .. y + dist]]
moveAfterTurn :: (Direction -> Direction) -> Int -> Point -> Velocity -> (PlayerTrail, Velocity) turn :: (Direction -> Direction) -> Velocity -> Velocity
moveAfterTurn turn timeElapsed point (Velocity speed dir) = turn turnFn (Velocity speed dir) =
let vel' = Velocity speed $ turn dir Velocity speed $ turnFn dir
in (move timeElapsed point vel', vel')
moveAndTurn :: (Direction -> Direction) -> Int -> Point -> Velocity -> (PlayerTrail, Velocity)
moveAndTurn turnFn timeElapsed point vel =
(move timeElapsed point vel, turn turnFn vel)
checkTrail :: GameMap -> PlayerTrail -> (PlayerTrail, PlayerState) checkTrail :: GameMap -> PlayerTrail -> (PlayerTrail, PlayerState)
checkTrail GameMap{..} trail = checkTrail GameMap{..} trail =
@ -45,21 +48,21 @@ checkTrail GameMap{..} trail =
else (trail', PlayerDead) else (trail', PlayerDead)
stepGame :: Game -> Int -> InEvent -> (Game, [OutEvent]) stepGame :: Game -> Int -> InEvent -> (Game, [OutEvent])
stepGame game@Game{gameMap = gameMap@GameMap{..}, ..} timeElapsed = stepGame' stepGame game@Game{gameMap = gameMap@GameMap{..}, ..} time = stepGame'
where where
stepGame' (InPlayerTurnLeft playerId) = stepGame' (InPlayerTurnLeft playerId) =
stepTurnEvent playerId $ moveAfterTurn leftTurn timeElapsed stepTurnEvent playerId $ moveAndTurn leftTurn
stepGame' (InPlayerTurnRight playerId) = stepGame' (InPlayerTurnRight playerId) =
stepTurnEvent playerId $ moveAfterTurn rightTurn timeElapsed stepTurnEvent playerId $ moveAndTurn rightTurn
stepGame' (InPlayerIdle playerId) = stepGame' (InPlayerIdle playerId) =
stepTurnEvent playerId $ moveAfterTurn noTurn timeElapsed stepTurnEvent playerId $ moveAndTurn noTurn
stepTurnEvent pId moveFn = stepTurnEvent pId moveFn =
flip (maybe (game, [])) (Map.lookup pId gamePlayers) $ \player@Player{..} -> flip (maybe (game, [])) (Map.lookup pId gamePlayers) $ \player@Player{..} ->
if playerState /= PlayerAlive if playerState /= PlayerAlive
then (game, []) then (game, [])
else let else let
(revTrail, vel'@(Velocity _ dir')) = moveFn playerPosition playerVelocity (revTrail, vel'@(Velocity _ dir')) = moveFn (time - playerLastEvent) playerPosition playerVelocity
(checkedTrail, playerState') = checkTrail gameMap revTrail (checkedTrail, playerState') = checkTrail gameMap revTrail
trail = reverse checkedTrail trail = reverse checkedTrail
pos' = if null trail then playerPosition else head trail pos' = if null trail then playerPosition else head trail
@ -68,6 +71,7 @@ stepGame game@Game{gameMap = gameMap@GameMap{..}, ..} timeElapsed = stepGame'
, playerVelocity = vel' , playerVelocity = vel'
, playerTrail = trail ++ playerTrail , playerTrail = trail ++ playerTrail
, playerScore = playerScore + score playerPosition pos' , playerScore = playerScore + score playerPosition pos'
, playerLastEvent = time
} }
gameMap' = gameMap { gameMapBlockedPoints = gameMap' = gameMap { gameMapBlockedPoints =
foldl' (flip Set.insert) gameMapBlockedPoints trail } foldl' (flip Set.insert) gameMapBlockedPoints trail }
@ -81,6 +85,6 @@ stepGame game@Game{gameMap = gameMap@GameMap{..}, ..} timeElapsed = stepGame'
runGame :: Game -> [(Int, InEvent)] -> (Game, [OutEvent]) runGame :: Game -> [(Int, InEvent)] -> (Game, [OutEvent])
runGame initialGame inEvents = runGame initialGame inEvents =
foldl (\(game, outEvents) (timeElapsed, inEvent) -> foldl (\(game, outEvents) (time, inEvent) ->
fmap (outEvents ++) $ stepGame game timeElapsed inEvent) fmap (outEvents ++) $ stepGame game time inEvent)
(initialGame, []) inEvents (initialGame, []) inEvents

View File

@ -36,6 +36,7 @@ data Player = Player { playerId :: PlayerId
, playerTrail :: PlayerTrail , playerTrail :: PlayerTrail
, playerBoost :: PlayerBoost , playerBoost :: PlayerBoost
, playerScore :: PlayerScore , playerScore :: PlayerScore
, playerLastEvent :: Int
} deriving (Show, Eq) } deriving (Show, Eq)
data PlayerEndState = PlayerWinner | PlayerLoser | PlayerDropped data PlayerEndState = PlayerWinner | PlayerLoser | PlayerDropped