Skip to content

Instantly share code, notes, and snippets.

@nitrix
Last active October 15, 2021 05:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nitrix/e7d04267fc91bbb764bdbb2e8879a47f to your computer and use it in GitHub Desktop.
Save nitrix/e7d04267fc91bbb764bdbb2e8879a47f to your computer and use it in GitHub Desktop.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TemplateHaskell #-}
module Kawaii.Game
( Game
, GameState(..)
, defaultGameState
, evalGame
, gameLiftIO
, runGame
, moveCamera
) where
import Control.Monad
import Control.Monad.State (StateT, MonadState, liftIO, runStateT, liftM)
import Data.Label (mkLabel)
import Data.Label.Monadic (modify)
import Kawaii.Camera
import Kawaii.Direction
newtype Game a = Game { unwrapGame :: StateT GameState IO a } deriving (Functor, Applicative, Monad, MonadState GameState)
data GameState = GameState
{ _gsCamera :: Camera
}
mkLabel ''GameState
defaultGameState :: GameState
defaultGameState = GameState defaultCamera
-- This lets us lift IO operation into our Game monad,
-- yet not derive MonadIO which would give too much power to the users of this Game module/type.
gameLiftIO :: IO a -> Game a
gameLiftIO = Game . liftIO
runGame :: Game a -> GameState -> IO (a, GameState)
runGame = runStateT . unwrapGame
evalGame :: Game a -> GameState -> IO a
evalGame game gameState = liftM fst (runGame game gameState) -- TODO: So tempted to use (.:) = (.) . (.) here.
moveCamera :: Int -> Direction -> Game ()
moveCamera delta direction = modify gsCamera (cameraTranslate delta direction)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment