aboutsummaryrefslogtreecommitdiff
path: root/Demos
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-01-01 11:39:25 -0800
committer3gg <3gg@shellblade.net>2025-01-01 11:39:25 -0800
commitacc954c9ac3a18e2d48e52839a7dc751597dfb15 (patch)
treee002438e1085cbda09a36ef81c4d661e0102a0d1 /Demos
parent8984aede0162f6bdcfc2dc0a54f563a3b1ff5684 (diff)
Streamling the Game monad, use MonadIO for automatic lifting.
Diffstat (limited to 'Demos')
-rw-r--r--Demos/Pong/Main.hs62
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
1module Main where 3module Main where
2 4
3import Pong 5import Pong
@@ -21,15 +23,16 @@ import Control.Monad (when)
21import Data.Maybe (mapMaybe) 23import Data.Maybe (mapMaybe)
22 24
23 25
24data GameState = GameState 26data 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
33type GameState = AppState Pong
34
35
33options = defaultAppOptions { title = "Pong" } 36options = defaultAppOptions { title = "Pong" }
34 37
35app = App options initGame endGame step render resize 38app = App options initGame endGame step render resize
@@ -38,32 +41,38 @@ app = App options initGame endGame step render resize
38main :: IO () 41main :: IO ()
39main = runApp app 42main = runApp app
40 43
41initGame :: AppContext -> Game () GameState 44initGame :: Game AppContext Pong
42initGame context = do 45initGame = 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
55endGame :: Game GameState () 62endGame :: Game GameState ()
56endGame = do 63endGame = 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
61step :: Elapsed -> Dt -> [InputEvent] -> Game GameState Bool 69step :: Elapsed -> Dt -> [InputEvent] -> Game GameState Bool
62step elapsed dt inputEvents = do 70step 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
80render :: Game GameState () 89render :: Game GameState ()
81render = do 90render = 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
95render' :: [GameObject] -> Game ImmRenderState () 103render' :: [GameObject] -> Game ImmRenderState ()
96render' world = do 104render' 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 }