I want to code a game in Haskell where every iteration of the loop computes the state of the world. I thought I should create a function:
gameLoop :: World -> World
-- ...
and have main :: IO ()
call it:
main = do
gameLoop -- ...
But the problem is that I'm missing some fundamental understanding of how to wrap the gameLoop
function so that it returns main
's parameter value.
How would one go about creating a game loop in Haskell?
You'll probably want something like this
import Control.Monad.Loops
main = iterateM_
(\w -> displayWorld w >> return (gameLoop w))
initWorld
-- iterateM_ ((>>) <$> displayWorld <*> return . gameLoop) initWorld
Or if you don't want to use the whole monad-loops package (even though it rocks)
main = loop initWorld
where loop w = displayWorld w >> loop (gameLoop w)
Basically you're just drawing the world, then looping again to with the next state.
More likely you want something like this though
-- False when the user wants to exit the game
keepGoing :: World -> Bool
main = iterateUntilM_ keepGoing displayLoop initWorld
where displayLoop w = displayWorld w >> return (gameLoop w)
Since otherwise you can't stop :)
I think what you declared is a state transition function, and the game loop itself should be a recursive function. The general idea looks like this:
initialState :: World
nextState :: World -> World
isFinalState :: World -> Bool
gameLoop world | isFinalState world = -- ...
| otherwise = do
drawScene world
gameLoop (nextState world)
main = gameLoop initialState
In initialState
the initial world can be constructed with initial parameters, etc. And in nextState
you can process player inputs (keyboards, etc.) which will change the state of the world. isFinalState
is used to detect whether we should exit the game loop.
This structure is somewhat similar to that frequently used in Erlang, e.g. Query an Erlang process for its state?