diff options
author | 3gg <3gg@shellblade.net> | 2025-01-01 11:39:25 -0800 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2025-01-01 11:39:25 -0800 |
commit | acc954c9ac3a18e2d48e52839a7dc751597dfb15 (patch) | |
tree | e002438e1085cbda09a36ef81c4d661e0102a0d1 /Demos | |
parent | 8984aede0162f6bdcfc2dc0a54f563a3b1ff5684 (diff) |
Streamling the Game monad, use MonadIO for automatic lifting.
Diffstat (limited to 'Demos')
-rw-r--r-- | Demos/Pong/Main.hs | 62 |
1 files changed, 35 insertions, 27 deletions
diff --git a/Demos/Pong/Main.hs b/Demos/Pong/Main.hs index f77136f..eafa983 100644 --- a/Demos/Pong/Main.hs +++ b/Demos/Pong/Main.hs | |||
@@ -1,3 +1,5 @@ | |||
1 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
2 | |||
1 | module Main where | 3 | module Main where |
2 | 4 | ||
3 | import Pong | 5 | import Pong |
@@ -21,15 +23,16 @@ import Control.Monad (when) | |||
21 | import Data.Maybe (mapMaybe) | 23 | import Data.Maybe (mapMaybe) |
22 | 24 | ||
23 | 25 | ||
24 | data GameState = GameState | 26 | data Pong = Pong |
25 | { context :: AppContext | 27 | { immRenderState :: ImmRenderState |
26 | , renderCoreState :: RenderCoreState | ||
27 | , immRenderState :: ImmRenderState | ||
28 | , viewProjection :: Matrix4 | 28 | , viewProjection :: Matrix4 |
29 | , backgroundMusic :: SoundSource | 29 | , backgroundMusic :: SoundSource |
30 | , world :: [GameObject] | 30 | , world :: [GameObject] |
31 | } | 31 | } |
32 | 32 | ||
33 | type GameState = AppState Pong | ||
34 | |||
35 | |||
33 | options = defaultAppOptions { title = "Pong" } | 36 | options = defaultAppOptions { title = "Pong" } |
34 | 37 | ||
35 | app = App options initGame endGame step render resize | 38 | app = App options initGame endGame step render resize |
@@ -38,32 +41,38 @@ app = App options initGame endGame step render resize | |||
38 | main :: IO () | 41 | main :: IO () |
39 | main = runApp app | 42 | main = runApp app |
40 | 43 | ||
41 | initGame :: AppContext -> Game () GameState | 44 | initGame :: Game AppContext Pong |
42 | initGame context = do | 45 | initGame = do |
43 | (immRenderState, renderCoreState) <- runSiblingGame newImmRenderer newRenderCoreState | 46 | renderCoreState <- contextRenderCoreState <$> get |
44 | (music, soundState') <- flip runSiblingGame (appSoundState context) $ do | 47 | (immRenderState, renderCoreState') <- runSiblingGame renderCoreState newImmRenderer |
48 | -- TODO: This can work if we use FlexibleContexts and change the function signatures. | ||
49 | --immRenderState <- newImmRenderer | ||
50 | music <- siblingGame $ do | ||
45 | musicBuffer <- loadAudioFile "/home/jeanne/Casual Tiki Party Main.wav" | 51 | musicBuffer <- loadAudioFile "/home/jeanne/Casual Tiki Party Main.wav" |
46 | music <- makeSoundSource | 52 | music <- makeSoundSource |
47 | liftIO $ do | 53 | -- TODO: setSoundSourceBuffer generates an AL error for some reason, though |
48 | setSoundSourceBuffer music musicBuffer | 54 | -- the music still plays. |
49 | setSoundLoopMode music Loop | 55 | -- "user error (runALUT: There was already an AL error on entry to an ALUT function)" |
50 | playSounds [music] | 56 | setSoundSourceBuffer music musicBuffer |
57 | setSoundLoopMode music Loop | ||
58 | playSounds [music] | ||
51 | return music | 59 | return music |
52 | let context' = context { appSoundState = soundState' } | 60 | return $ Pong immRenderState Matrix4.id music newWorld |
53 | return $ GameState context' renderCoreState immRenderState Matrix4.id music newWorld | ||
54 | 61 | ||
55 | endGame :: Game GameState () | 62 | endGame :: Game GameState () |
56 | endGame = do | 63 | endGame = do |
57 | game <- get | 64 | renderCoreState <- appRenderCoreState <$> get |
58 | runSubGame' (deleteImmRenderer $ immRenderState game) (renderCoreState game) | 65 | game <- getGameState |
66 | exec' runSiblingGame renderCoreState (deleteImmRenderer $ immRenderState game) | ||
59 | 67 | ||
60 | 68 | ||
61 | step :: Elapsed -> Dt -> [InputEvent] -> Game GameState Bool | 69 | step :: Elapsed -> Dt -> [InputEvent] -> Game GameState Bool |
62 | step elapsed dt inputEvents = do | 70 | step elapsed dt inputEvents = do |
63 | gameState <- get | 71 | appState <- get |
64 | events <- processInput (appWindow . context $ gameState) | 72 | gameState <- getGameState |
73 | events <- processInput (appWindow appState) | ||
65 | --when (events /= []) $ liftIO . putStrLn $ show events | 74 | --when (events /= []) $ liftIO . putStrLn $ show events |
66 | modify $ \gameState -> gameState | 75 | modifyGameState $ \pong -> pong |
67 | { world = stepWorld (realToFrac elapsed) (realToFrac dt) events (world gameState) | 76 | { world = stepWorld (realToFrac elapsed) (realToFrac dt) events (world gameState) |
68 | } | 77 | } |
69 | return (not $ exitRequested inputEvents) | 78 | return (not $ exitRequested inputEvents) |
@@ -79,18 +88,17 @@ exitRequested = elem (KeyDown KEY_ESC) | |||
79 | 88 | ||
80 | render :: Game GameState () | 89 | render :: Game GameState () |
81 | render = do | 90 | render = do |
82 | gameState <- get | 91 | gameState <- getGameState |
83 | immRenderState' <- flip execSubGame (immRenderState gameState) $ do | 92 | immRenderState' <- exec runSiblingGame (immRenderState gameState) $ do |
84 | immStart | 93 | immStart |
85 | immSetViewProjectionMatrix (viewProjection gameState) | 94 | immSetViewProjectionMatrix (viewProjection gameState) |
86 | -- Clear the background to a different colour than the playable area to make | 95 | -- Clear the background to a different colour than the playable area to make |
87 | -- the latter distinguishable. | 96 | -- the latter distinguishable. |
88 | liftIO $ do | 97 | setClearColour (0.2, 0.2, 0.2, 0.0) |
89 | setClearColour (0.2, 0.2, 0.2, 0.0) | 98 | clearBuffers [ColourBuffer] |
90 | clearBuffers [ColourBuffer] | ||
91 | render' $ world gameState | 99 | render' $ world gameState |
92 | immEnd | 100 | immEnd |
93 | put $ gameState { immRenderState = immRenderState' } | 101 | putGameState $ gameState { immRenderState = immRenderState' } |
94 | 102 | ||
95 | render' :: [GameObject] -> Game ImmRenderState () | 103 | render' :: [GameObject] -> Game ImmRenderState () |
96 | render' world = do | 104 | render' world = do |
@@ -132,7 +140,7 @@ resize (ResizeEvent w h) = | |||
132 | bottom = if r > 1 then 0 else -pad | 140 | bottom = if r > 1 then 0 else -pad |
133 | top = if r > 1 then 1 else 1 + pad | 141 | top = if r > 1 then 1 else 1 + pad |
134 | in do | 142 | in do |
135 | liftIO $ setViewport 0 0 w h | 143 | setViewport 0 0 w h |
136 | modify $ \state -> state { | 144 | modifyGameState $ \pong -> pong { |
137 | viewProjection = Matrix4.ortho left right bottom top (-1) 1 | 145 | viewProjection = Matrix4.ortho left right bottom top (-1) 1 |
138 | } | 146 | } |