How do I write a game loop in Haskell?

2019-02-11 22:29发布

问题:

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?

回答1:

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 :)



回答2:

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?