私のお気に入りの引用の 1 つを繰り返すには
... 世界の状態を取り込み、新しい世界を返すため、純粋なままです。
これは、Haskell のいとこである Clean について話していましたが、それでも関連しています。その要点は、その通りです。ある種の状態が必要ですが、変更可能である必要はありません。検討
myFun :: StateOfTheWorld -> a -> (StateOfTheWorld, b)
そのため、状態を変更するのではなく、新しい状態を生成するだけです。世界の同じ状態と同じアクションが与えられた場合、同じものが返されるため、これは参照透過的です。
あなたのために、あなたは次のようなものを持っているかもしれません
killPlayer :: Game -> Event -> Game
killPlayer g (Kill x) = g { isDead = x : isDead g }
これは、レコードの機能更新を使用しているだけです。これは少し不格好なので、次のようにするかもしれません
killPlayer :: Game -> Event -> Action
killPlayer (PlayerDamaged x amount) = if playerHealth g x <= amount
then KillPlayer x
else ReduceHealth x amount
したがって、完全なゲームの状態ではなく、違いを返すだけです。
これは機能しますが、醜いです。そこで、do
記法と Control.Monad.State でこれをきれいにします。これは恐ろしく聞こえるかもしれませんが、構文をもう少し抽象化しただけで、まさに上で行っていたことです。実際、これはIO
GHCにもあります。あなたがモナドについて学んだかどうかはわかりませんが、State モナドはしばしば動機付けの例です。
最後にゲームに戻ると、私が見たゲームフレームワークの多くは次のようなものです: イベントをリッスンし、ゲームの状態に小さな増分変更を提案し、異なるものを返します。最後に、フレームワーク自体が適切な openGL 呼び出しを行います。またはそれらの変更を実装するもの。