Revert "Non effectful renderer"

This reverts commit afe32a1b0d.
This commit is contained in:
magic_rb 2024-01-26 23:13:12 +01:00
parent afe32a1b0d
commit c29607e1c3
6 changed files with 151 additions and 143 deletions

View file

@ -35,13 +35,12 @@ getCamera eff (dimX, dimY) = do
} }
playerMovement playerMovement
:: forall w es r :: forall w es
. ( AE.ECS w :> es . ( AE.ECS w :> es
, AE.Get w VelocityComponent , AE.Get w VelocityComponent
, Renderer (Eff es) r , Renderer :> es
) )
=> r => AE.Entity
-> AE.Entity
-> ( RL.KeyboardKey -> ( RL.KeyboardKey
, RL.KeyboardKey , RL.KeyboardKey
, RL.KeyboardKey , RL.KeyboardKey
@ -49,14 +48,14 @@ playerMovement
) )
-> Float -> Float
-> Eff es () -> Eff es ()
playerMovement renderer player (left, right, up, down) speed = do playerMovement player (left, right, up, down) speed = do
directions <- directions <-
mapM mapM
(\tuple -> fst tuple <&> (,snd tuple)) (\tuple -> fst tuple <&> (,snd tuple))
[ (isKeyDown renderer left, V2 (-1.0) 0) [ (isKeyDown left, V2 (-1.0) 0)
, (isKeyDown renderer right, V2 1.0 0) , (isKeyDown right, V2 1.0 0)
, (isKeyDown renderer down, V2 0 1.0) , (isKeyDown down, V2 0 1.0)
, (isKeyDown renderer up, V2 0 (-1.0)) , (isKeyDown up, V2 0 (-1.0))
] ]
let movement = foldl (+) (V2 0 0) $ map snd $ filter fst directions let movement = foldl (+) (V2 0 0) $ map snd $ filter fst directions
AE.set @w @VelocityComponent player (Velocity (normalize movement * pure speed)) AE.set @w @VelocityComponent player (Velocity (normalize movement * pure speed))

View file

@ -54,6 +54,7 @@ instance EngineConstraints where
, Reads camera RL.Camera2D :> es , Reads camera RL.Camera2D :> es
, Reads backgroundColor RL.Color :> es , Reads backgroundColor RL.Color :> es
, IOE :> es , IOE :> es
, Renderer :> es
, AE.ECS w :> es , AE.ECS w :> es
) )
@ -63,14 +64,11 @@ startEngine
(backgroundColor :: Symbol) (backgroundColor :: Symbol)
(w :: Type) (w :: Type)
es es
r
. ( EngineConstraint camera backgroundColor es w . ( EngineConstraint camera backgroundColor es w
, Game :> es , Game :> es
, Renderer (Eff es) r
) )
=> r => Eff es ()
-> Eff es () startEngine = do
startEngine renderer = do
gameInput gameInput
applyVelocity'' @w applyVelocity'' @w
@ -82,12 +80,12 @@ startEngine renderer = do
c <- readVal @camera @RL.Camera2D c <- readVal @camera @RL.Camera2D
color <- readVal @backgroundColor @RL.Color color <- readVal @backgroundColor @RL.Color
beginFrame renderer c color beginFrame c color
-- getFPS >>= unsafeEff_ . print -- getFPS >>= unsafeEff_ . print
AE.cmapM_ @w @(PositionComponent, BoxComponent) AE.cmapM_ @w @(PositionComponent, BoxComponent)
(drawSprite renderer) drawSprite
-- AE.cmapM_ -- AE.cmapM_
-- @w -- @w
-- @PositionComponent -- @PositionComponent
@ -95,7 +93,7 @@ startEngine renderer = do
-- drawLine (V2 (x - 0.1) (y - 0.1)) (V2 (x + 0.1) (y + 0.1)) RL.red -- drawLine (V2 (x - 0.1) (y - 0.1)) (V2 (x + 0.1) (y + 0.1)) RL.red
-- >> drawLine (V2 (x + 0.1) (y - 0.1)) (V2 (x - 0.1) (y + 0.1)) RL.red -- >> drawLine (V2 (x + 0.1) (y - 0.1)) (V2 (x - 0.1) (y + 0.1)) RL.red
endFrame renderer endFrame
-- renderBoundingBoxes @w -- renderBoundingBoxes @w
-- renderCollision @w -- renderCollision @w

View file

@ -116,7 +116,7 @@ readsCamera = do
(pure camera) (pure camera)
windowDimensions windowDimensions
runGame :: forall es. (IOE :> es, AE.ECS World :> es, State GameState :> es) => Eff (Game : es) () -> Eff es () runGame :: forall es. (IOE :> es, AE.ECS World :> es, State GameState :> es, Renderer :> es) => Eff (Game : es) () -> Eff es ()
runGame = interpret \env eff -> runGame = interpret \env eff ->
case eff of case eff of
GameInput -> do GameInput -> do
@ -183,7 +183,8 @@ runGame = interpret \env eff ->
pure () pure ()
initialize initialize
:: Eff es () :: (Renderer :> es)
=> Eff es ()
initialize = do initialize = do
pure () pure ()
@ -196,11 +197,11 @@ main' = do
. runGameState . runGameState
. runGameConfig . runGameConfig
$ gets @GameState (\s -> (s ^. windowDimensions . _x, s ^. windowDimensions . _y)) >>= \(dimX, dimY) -> $ gets @GameState (\s -> (s ^. windowDimensions . _x, s ^. windowDimensions . _y)) >>= \(dimX, dimY) ->
runGame $ runRaylibRenderer dimX dimY "App"
withRaylibRenderer dimX dimY "App" \renderer -> . runGame
initialize >> whileM do $ initialize >> whileM do
engineEnv $ startEngine @"state.camera" @"config.backgroundColor" @World renderer engineEnv $ startEngine @"state.camera" @"config.backgroundColor" @World
not <$> windowShouldClose renderer not <$> windowShouldClose
where where
readsBackgroundColor readsBackgroundColor
:: (Reader GameConfig :> es) :: (Reader GameConfig :> es)

View file

@ -64,23 +64,22 @@ makeLensesFor
''GameConfig ''GameConfig
playerMovement playerMovement
:: forall w es r :: forall w es
. ( Renderer (Eff es) r . ( Renderer :> es
, AE.Get w PositionComponent , AE.Get w PositionComponent
, AE.Set w VelocityComponent , AE.Set w VelocityComponent
, AE.ECS w :> es , AE.ECS w :> es
, Reader GameConfig :> es , Reader GameConfig :> es
) )
=> r => (RL.KeyboardKey, Float)
-> (RL.KeyboardKey, Float)
-> (RL.KeyboardKey, Float) -> (RL.KeyboardKey, Float)
-> Eff es AE.Entity -> Eff es AE.Entity
-> Eff es () -> Eff es ()
playerMovement renderer (up, upSpeed) (down, downSpeed) entity = do playerMovement (up, upSpeed) (down, downSpeed) entity = do
entity' <- entity entity' <- entity
down <- isKeyDown renderer down down <- isKeyDown down
up <- isKeyDown renderer up up <- isKeyDown up
AE.set @w entity' $ AE.set @w entity' $
case (down, up) of case (down, up) of
(True, False) -> Velocity $ V2 0 downSpeed (True, False) -> Velocity $ V2 0 downSpeed
@ -112,14 +111,13 @@ ballRespawn goal1 goal2 ball = do
ret ret
initialise initialise
:: ( State GameState :> es :: ( Renderer :> es
, State GameState :> es
, Reader GameConfig :> es , Reader GameConfig :> es
, AE.ECS World :> es , AE.ECS World :> es
, Renderer (Eff es) r
) )
=> r => Eff es ()
-> Eff es () initialise = do
initialise renderere = do
-- setTargetFPS 60 -- setTargetFPS 60
playArea <- asks @GameConfig (\s -> s.playArea) playArea <- asks @GameConfig (\s -> s.playArea)
@ -237,53 +235,50 @@ pongGame = do
{ playArea = 20 { playArea = 20
} }
-- RL.setTraceLogLevel RL.LogWarning -- RL.setTraceLogLevel RL.LogWarning
withRaylibRenderer gameState.dimX gameState.dimY "App" $ \renderer -> runEff . AE.runECS initWorld . evalState gameState . runReader gameConfig . runRaylibRenderer gameState.dimX gameState.dimY "App" $
runEff . AE.runECS initWorld . evalState gameState . runReader gameConfig $ initialise >> whileM do
initialise renderer >> whileM do playerMovement @World
playerMovement @World (RL.KeyW, -0.2)
renderer (RL.KeyS, 0.2)
(RL.KeyW, -0.2) (gets @GameState (\s -> s.player1))
(RL.KeyS, 0.2)
(gets @GameState (\s -> s.player1))
playerMovement @World playerMovement @World
renderer (RL.KeyUp, -0.2)
(RL.KeyUp, -0.2) (RL.KeyDown, 0.2)
(RL.KeyDown, 0.2) (gets @GameState (\s -> s.player2))
(gets @GameState (\s -> s.player2))
-- ballMovement -- ballMovement
-- (gets @GameState (\s -> s.player1)) -- (gets @GameState (\s -> s.player1))
-- (gets @GameState (\s -> s.player2)) -- (gets @GameState (\s -> s.player2))
-- (gets @GameState (\s -> s.ball)) -- (gets @GameState (\s -> s.ball))
-- (gets @GameState (\s -> s.bottom)) -- (gets @GameState (\s -> s.bottom))
-- (gets @GameState (\s -> s.top)) -- (gets @GameState (\s -> s.top))
ballRespawn ballRespawn
(gets @GameState (\s -> s.goal2)) (gets @GameState (\s -> s.goal2))
(gets @GameState (\s -> s.goal1)) (gets @GameState (\s -> s.goal1))
(gets @GameState (\s -> s.ball)) (gets @GameState (\s -> s.ball))
collisionAABB @World collisionAABB @World
applyVelocity'' @World applyVelocity'' @World
resolveAABB @World resolveAABB @World
-- AE.cmapM_ @World @(AE.Entity, PositionComponent, CollisionComponent) \(entity, position, collision) -> -- AE.cmapM_ @World @(AE.Entity, PositionComponent, CollisionComponent) \(entity, position, collision) ->
-- when (collision.colliders /= []) $ liftIO $ print (show entity <> " with " <> show collision.colliders <> " at " <> show position) -- when (collision.colliders /= []) $ liftIO $ print (show entity <> " with " <> show collision.colliders <> " at " <> show position)
score' <- gets @GameState (\s -> s.score) score' <- gets @GameState (\s -> s.score)
-- gets @GameState (\s -> s.separator) >>= flip (AE.modify @World @TextBoxComponent) \textBox -> -- gets @GameState (\s -> s.separator) >>= flip (AE.modify @World @TextBoxComponent) \textBox ->
-- textBox{text = T.pack $ show score'} -- textBox{text = T.pack $ show score'}
dims <- gets @GameState (\s -> (s.dimX, s.dimY)) dims <- gets @GameState (\s -> (s.dimX, s.dimY))
camera <- getCamera @World (gets @GameState (\s -> s.camera)) dims camera <- getCamera @World (gets @GameState (\s -> s.camera)) dims
-- getFPS >>= unsafeEff_ . print -- getFPS >>= unsafeEff_ . print
beginFrame renderer camera RL.white beginFrame camera RL.white
AE.cmapM_ @World @(PositionComponent, BoxComponent) (drawSprite renderer) AE.cmapM_ @World @(PositionComponent, BoxComponent) drawSprite
-- (gets @GameState (\s -> s.score)) >>= liftIO . print -- (gets @GameState (\s -> s.score)) >>= liftIO . print
-- render @World -- render @World
-- renderOrigins @World -- renderOrigins @World
-- renderBoundingBoxes @World -- renderBoundingBoxes @World
not <$> windowShouldClose renderer not <$> windowShouldClose

View file

@ -152,15 +152,14 @@ initialise = do
pure () pure ()
runGame runGame
:: forall es r :: forall es
. ( AE.ECS LocalWorld :> es . ( AE.ECS LocalWorld :> es
, Renderer :> es
, State GameState :> es , State GameState :> es
, Renderer (Eff es) r
) )
=> r => Eff (Game : es) ()
-> Eff (Game : es) ()
-> Eff es () -> Eff es ()
runGame renderer = interpret \_ eff -> runGame = interpret \_ eff ->
case eff of case eff of
GameInput -> do GameInput -> do
playerEntity <- gets @GameState (\s -> s.playerEntity) playerEntity <- gets @GameState (\s -> s.playerEntity)
@ -169,7 +168,6 @@ runGame renderer = interpret \_ eff ->
-- Nothing -> Tag 0 -- Nothing -> Tag 0
-- AE.get @LocalWorld @(TagComponent Int) playerEntity >>= unsafeEff_ . print -- AE.get @LocalWorld @(TagComponent Int) playerEntity >>= unsafeEff_ . print
playerMovement @LocalWorld playerMovement @LocalWorld
renderer
playerEntity playerEntity
( RL.KeyA ( RL.KeyA
, RL.KeyD , RL.KeyD
@ -180,8 +178,8 @@ runGame renderer = interpret \_ eff ->
cameraEntity <- gets @GameState (\s -> s.cameraEntity) cameraEntity <- gets @GameState (\s -> s.cameraEntity)
isKeyDown renderer RL.KeyKpAdd >>= flip when (AE.modify @LocalWorld @CameraComponent @CameraComponent cameraEntity (\c -> c{zoom = c.zoom + 1})) isKeyDown RL.KeyKpAdd >>= flip when (AE.modify @LocalWorld @CameraComponent @CameraComponent cameraEntity (\c -> c{zoom = c.zoom + 1}))
isKeyDown renderer RL.KeyKpSubtract >>= flip when (AE.modify @LocalWorld @CameraComponent @CameraComponent cameraEntity (\c -> c{zoom = c.zoom - 1})) isKeyDown RL.KeyKpSubtract >>= flip when (AE.modify @LocalWorld @CameraComponent @CameraComponent cameraEntity (\c -> c{zoom = c.zoom - 1}))
pure () pure ()
GamePhysics -> pure () GamePhysics -> pure ()
GameRendering _ -> do GameRendering _ -> do
@ -209,18 +207,18 @@ main' = do
print $ perlin 0 0 print $ perlin 0 0
-- RL.setTraceLogLevel RL.LogWarning -- RL.setTraceLogLevel RL.LogWarning
withRaylibRenderer gameState.dimX gameState.dimY "App" \renderer -> runEff
runEff . AE.runECS initWorld
. AE.runECS initWorld . evalState gameState
. evalState gameState . runReader gameConfig
. runReader gameConfig . runRaylibRenderer gameState.dimX gameState.dimY "App"
. runReads @"config.camera" @RL.Camera2D do . runReads @"config.camera" @RL.Camera2D do
dims <- gets @GameState (\s -> (s.dimX, s.dimY)) dims <- gets @GameState (\s -> (s.dimX, s.dimY))
getCamera @LocalWorld (gets @GameState (\s -> s.cameraEntity)) dims getCamera @LocalWorld (gets @GameState (\s -> s.cameraEntity)) dims
. runReads @"config.backgroundColor" @RL.Color (pure RL.white) . runReads @"config.backgroundColor" @RL.Color (pure RL.white)
. runGame renderer . runGame
$ initialise >> whileM do $ initialise >> whileM do
startEngine @"config.camera" @"config.backgroundColor" @LocalWorld renderer startEngine @"config.camera" @"config.backgroundColor" @LocalWorld
not <$> windowShouldClose renderer not <$> windowShouldClose
pure () pure ()

View file

@ -7,15 +7,14 @@
{-# OPTIONS_GHC -fplugin-opt=Foreign.Storable.Generic.Plugin:-v1 #-} {-# OPTIONS_GHC -fplugin-opt=Foreign.Storable.Generic.Plugin:-v1 #-}
{-# OPTIONS_GHC -fplugin=Foreign.Storable.Generic.Plugin #-} {-# OPTIONS_GHC -fplugin=Foreign.Storable.Generic.Plugin #-}
module System.Renderer (Renderer (..), withRaylibRenderer, beginFrame, drawSprite, drawLine, isKeyDown, windowShouldClose, endFrame) where module System.Renderer (Renderer (..), runRaylibRenderer, beginFrame, drawSprite, drawLine, isKeyDown, windowShouldClose, endFrame) where
import Apecs.Effectful qualified as AE import Apecs.Effectful qualified as AE
import Control.Lens import Control.Lens
import Control.Monad import Control.Monad
import Control.Monad.Primitive import Control.Monad.Primitive (PrimState)
import Data.IORef import Data.IORef
import Data.Text (Text) import Data.Text (Text)
import Data.Text qualified as T
import Data.Vector.Storable qualified as VS hiding (unsafeToForeignPtr) import Data.Vector.Storable qualified as VS hiding (unsafeToForeignPtr)
import Data.Vector.Storable.Mutable qualified as VS import Data.Vector.Storable.Mutable qualified as VS
import Effectful import Effectful
@ -34,59 +33,77 @@ import Raylib.Types qualified as RL
import Raylib.Util.Colors qualified as RL import Raylib.Util.Colors qualified as RL
import World import World
class Renderer m a where data Renderer :: Effect where
beginFrame :: a -> RL.Camera2D -> RL.Color -> m () BeginFrame :: RL.Camera2D -> RL.Color -> Renderer (Eff es) ()
drawSprite :: a -> (PositionComponent, BoxComponent) -> m () DrawSprite :: (PositionComponent, BoxComponent) -> Renderer (Eff es) ()
drawLine :: a -> V2 Float -> V2 Float -> RL.Color -> m () DrawLine :: V2 Float -> V2 Float -> RL.Color -> Renderer (Eff es) ()
windowShouldClose :: a -> m Bool WindowShouldClose :: Renderer (Eff es) Bool
isKeyDown :: a -> RL.KeyboardKey -> m Bool IsKeyDown :: RL.KeyboardKey -> Renderer (Eff es) Bool
endFrame :: a -> m () EndFrame :: Renderer (Eff es) ()
type instance DispatchOf Renderer = Dynamic
beginFrame :: (HasCallStack, Renderer :> es) => RL.Camera2D -> RL.Color -> Eff es ()
beginFrame camera color = send (BeginFrame camera color)
drawSprite :: (HasCallStack, Renderer :> es) => (PositionComponent, BoxComponent) -> Eff es ()
drawSprite d = send (DrawSprite d)
drawLine :: (HasCallStack, Renderer :> es) => V2 Float -> V2 Float -> RL.Color -> Eff es ()
drawLine start end color = send (DrawLine start end color)
windowShouldClose :: (HasCallStack, Renderer :> es) => Eff es Bool
windowShouldClose = send WindowShouldClose
isKeyDown :: (HasCallStack, Renderer :> es) => RL.KeyboardKey -> Eff es Bool
isKeyDown key = send (IsKeyDown key)
endFrame :: (HasCallStack, Renderer :> es) => Eff es ()
endFrame = send EndFrame
data RectangleInfo = RectangleInfo {position :: V2 Float, size :: V2 Float, color :: RL.Color} data RectangleInfo = RectangleInfo {position :: V2 Float, size :: V2 Float, color :: RL.Color}
deriving (Generic, GStorable) deriving (Generic, GStorable)
foreign import capi safe "raylib_batch.h" draw_rectangles_batch :: Ptr RectangleInfo -> CSize -> IO () foreign import capi safe "raylib_batch.h" draw_rectangles_batch :: Ptr RectangleInfo -> CSize -> IO ()
data RaylibRenderer = RaylibRenderer {indexRef :: IORef Int, vectorRef :: IORef (VS.MVector (PrimState IO) RectangleInfo)} runRaylibRenderer :: (IOE :> es) => Int -> Int -> Text -> Eff (Renderer : es) a -> Eff es a
runRaylibRenderer dimX dimY title go = do
withRaylibRenderer :: forall m a. (MonadIO m) => Int -> Int -> Text -> (RaylibRenderer -> m a) -> m a vectorRef <- liftIO $ VS.new @_ @RectangleInfo 4279 >>= newIORef
withRaylibRenderer dimX dimY title go = do
winRes <- liftIO $ RL.initWindow dimX dimY (T.unpack title)
vectorRef <- liftIO (VS.new @_ @RectangleInfo 4279) >>= liftIO . newIORef
indexRef <- indexRef <-
liftIO $ liftIO $
newIORef newIORef
(0 :: Int) (0 :: Int)
go (RaylibRenderer indexRef vectorRef) reinterpret
(runRaylibWindow dimX dimY title)
( \_ -> \case
BeginFrame camera color -> do
liftIO $ RL.getFPS >>= liftIO . print
liftIO $ writeIORef indexRef 0
liftIO $ RL.beginDrawing
liftIO $ RL.clearBackground color
liftIO $ RL.beginMode2D camera
DrawSprite (Position position, Box{color, offset, size}) -> do
vector <- liftIO $ readIORef vectorRef
index <- liftIO $ readIORef indexRef
liftIO $ VS.write vector index (RectangleInfo position (V2 (size ^. _1) (size ^. _2)) color)
liftIO $ writeIORef indexRef (index + 1)
where
-- liftIO $ RL.drawRectangleV rlPosition rlSize color
instance (MonadIO m) => Renderer m RaylibRenderer where rlPosition = RL.Vector2 (position ^. _x + fst offset - (size ^. _1) / 2) (position ^. _y + snd offset - size ^. _2 / 2)
beginFrame (RaylibRenderer{indexRef}) camera color = do rlSize = RL.Vector2 (size ^. _1) (size ^. _2)
liftIO $ RL.getFPS >>= liftIO . print DrawLine start end color ->
liftIO $ writeIORef indexRef 0 liftIO $ RL.drawLineV (RL.Vector2 (start ^. _x) (start ^. _y)) (RL.Vector2 (end ^. _x) (end ^. _y)) color
liftIO $ RL.beginDrawing WindowShouldClose -> liftIO RL.windowShouldClose
liftIO $ RL.clearBackground color IsKeyDown key -> liftIO $ RL.isKeyDown key
liftIO $ RL.beginMode2D camera EndFrame -> do
drawSprite (RaylibRenderer{indexRef, vectorRef}) (Position position, Box{color, offset, size}) = do vector <- liftIO $ readIORef vectorRef
vector <- liftIO $ readIORef vectorRef index <- liftIO $ readIORef indexRef
index <- liftIO $ readIORef indexRef let (fptr, offset, length) = (VS.unsafeToForeignPtr vector)
liftIO $ VS.write vector index (RectangleInfo position (V2 (size ^. _1) (size ^. _2)) color) liftIO $ withForeignPtr fptr \ptr -> draw_rectangles_batch (plusPtr ptr offset) (fromIntegral length)
liftIO $ writeIORef indexRef (index + 1) liftIO RL.endMode2D
where liftIO RL.endDrawing
-- liftIO $ RL.drawRectangleV rlPosition rlSize color )
go
rlPosition = RL.Vector2 (position ^. _x + fst offset - (size ^. _1) / 2) (position ^. _y + snd offset - size ^. _2 / 2)
rlSize = RL.Vector2 (size ^. _1) (size ^. _2)
drawLine (RaylibRenderer{}) start end color =
liftIO $ RL.drawLineV (RL.Vector2 (start ^. _x) (start ^. _y)) (RL.Vector2 (end ^. _x) (end ^. _y)) color
windowShouldClose _ = liftIO RL.windowShouldClose
isKeyDown _ key = liftIO $ RL.isKeyDown key
endFrame (RaylibRenderer{vectorRef, indexRef}) = do
vector <- liftIO $ readIORef vectorRef
index <- liftIO $ readIORef indexRef
let (fptr, offset, length) = (VS.unsafeToForeignPtr vector)
liftIO $ withForeignPtr fptr \ptr -> draw_rectangles_batch (plusPtr ptr offset) (fromIntegral length)
liftIO RL.endMode2D
liftIO RL.endDrawing
-- render -- render
-- :: forall w es -- :: forall w es