aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-02-05 23:18:30 +0000
committerJuan J. Martinez <jjm@usebox.net>2023-02-05 23:24:06 +0000
commitb9578c2a2c60d75c4a4d4519f10b99703ee5ea27 (patch)
tree286fb453a4c73daa4b8350dca1be5ea2cb21f0e9
parentfb1c60789db8e71584211cbef19811298c8fd6e6 (diff)
downloadspace-plat-hs-b9578c2a2c60d75c4a4d4519f10b99703ee5ea27.tar.gz
space-plat-hs-b9578c2a2c60d75c4a4d4519f10b99703ee5ea27.zip
Swpan new entities
- Each entity can generate a list of "spawns" (add a new entity) - Added a "dust" effect to the jump WIP TODO: probably wrap the entity list in a type so we don't need to pass the spritesheet to the update function.
-rw-r--r--data/sprites.json10
-rw-r--r--data/sprites.pngbin8068 -> 8565 bytes
-rw-r--r--src/Game.hs4
-rw-r--r--src/Game/Entities.hs41
4 files changed, 47 insertions, 8 deletions
diff --git a/data/sprites.json b/data/sprites.json
index af3e33e..6fddd4e 100644
--- a/data/sprites.json
+++ b/data/sprites.json
@@ -12,5 +12,15 @@
[0, 1, 0, 2],
[5, 4, 5, 3]
]
+ },
+ "dust": {
+ "frames": [
+ { "x": 0, "y": 24, "width": 16, "height": 24 },
+ { "x": 16, "y": 24, "width": 16, "height": 24 },
+ { "x": 32, "y": 24, "width": 16, "height": 24 }
+ ],
+ "sets": [
+ [0, 1, 2]
+ ]
}
}
diff --git a/data/sprites.png b/data/sprites.png
index 7ee2136..21ef84e 100644
--- a/data/sprites.png
+++ b/data/sprites.png
Binary files differ
diff --git a/src/Game.hs b/src/Game.hs
index 3121ddf..28e14e7 100644
--- a/src/Game.hs
+++ b/src/Game.hs
@@ -110,6 +110,7 @@ gameLoop = do
controls = _controls env
map' = _map env
entities = _entities env
+ sprites = _sprites env
events <- map SDL.eventPayload <$> SDL.pollEvents
@@ -125,8 +126,7 @@ gameLoop = do
SDL.rendererRenderTarget renderer $= Just canvas
SDL.clear renderer
- -- update entities filtering out the ones that have been destroyed
- updated <- liftIO $ fmap (filter (not . E.eDestroy)) (traverse (\e -> E.eUpdate e e) =<< readIORef entities)
+ updated <- liftIO $ E.update sprites =<< readIORef entities
entities $= updated
-- render map and entities
diff --git a/src/Game/Entities.hs b/src/Game/Entities.hs
index bd11235..0cfdb47 100644
--- a/src/Game/Entities.hs
+++ b/src/Game/Entities.hs
@@ -1,4 +1,4 @@
-module Game.Entities (Entity (..), toSpriteSet, mkPlayer, render) where
+module Game.Entities (Entity (..), toSpriteSet, mkPlayer, mkEffect, update, render) where
import Data.IORef
import qualified Game.Controller as C
@@ -7,7 +7,7 @@ import qualified SDL
data Dir = DirRight | DirLeft deriving (Eq)
-data Type = TypePlayer -- \| TypeEnemy | TypeItem
+data Type = TypePlayer | TypeEffect
toSpriteSet :: Dir -> Int
toSpriteSet DirRight = 0
@@ -31,6 +31,8 @@ gravityDown = 16
gravityTable :: [Int]
gravityTable = [0, 6, 4, 4, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 4]
+data Spawn = DustEffectSpawn Int Int
+
data Entity = Entity
{ eType :: Type,
eX :: Int,
@@ -43,23 +45,40 @@ data Entity = Entity
eSprite :: S.Sprite,
eUpdate :: Entity -> IO Entity,
eBlocked :: Int -> Int -> Bool,
- eDestroy :: Bool
+ eDestroy :: Bool,
+ eSpawns :: [Spawn]
}
+mkEffect :: S.SpriteSheet -> Int -> Int -> String -> IO Entity
+mkEffect sprites x y name = do
+ s <- S.get sprites name
+ pure $ Entity TypeEffect x y frameDelay 0 3 gravityOff DirRight s (pure . updateEffect) (\_ _ -> False) False []
+
+updateEffect :: Entity -> Entity
+updateEffect e
+ | delay > 0 = e {eDelay = delay - 1}
+ | frame + 1 < frameLimit = e {eDelay = frameDelay, eFrame = frame + 1}
+ | otherwise = e {eDestroy = True}
+ where
+ frame = eFrame e
+ frameLimit = eFrameLimit e
+ delay = eDelay e
+
mkPlayer :: S.SpriteSheet -> Int -> Int -> IORef C.Controls -> (Int -> Int -> Bool) -> IO Entity
mkPlayer sprites x y controls isBlocked = do
s <- S.get sprites "player"
- pure $ Entity TypePlayer x y 0 0 3 gravityOff DirRight s (updatePlayer controls) isBlocked False
+ pure $ Entity TypePlayer x y 0 0 3 gravityOff DirRight s (updatePlayer controls) isBlocked False []
updateFrame :: Bool -> Entity -> Entity
updateFrame updated e
| isGravityOn = e
| delay > 0 = e {eDelay = delay - 1}
- | frame < eFrameLimit e = e {eDelay = frameDelay, eFrame = if updated then frame + 1 else 0}
+ | frame < frameLimit = e {eDelay = frameDelay, eFrame = if updated then frame + 1 else 0}
| otherwise = e {eDelay = frameDelay, eFrame = 0}
where
isGravityOn = eGravity e > gravityOff
frame = eFrame e
+ frameLimit = eFrameLimit e
delay = eDelay e
updateHorizontal :: Bool -> Bool -> Entity -> Entity
@@ -84,7 +103,7 @@ updateHorizontal left right e
updateVertical :: Bool -> Bool -> Entity -> Entity
updateVertical jump down e
| not jump || gravity /= gravityOff = e
- | not down = e {eGravity = gravityUp, eFrame = jumpFrame}
+ | not down = e {eGravity = gravityUp, eFrame = jumpFrame, eSpawns = events ++ [DustEffectSpawn x (y + 8)]}
-- go down a 8 pixel tall platform; not ideal to have these values hardcoded here
-- but to be fair, the player height/width is hardcoded as well
| down
@@ -97,6 +116,7 @@ updateVertical jump down e
y = eY e
gravity = eGravity e
isBlocked = eBlocked e
+ events = eSpawns e
applyGravity :: Int -> Entity -> Entity
applyGravity v e
@@ -138,6 +158,15 @@ updatePlayer controls e = do
-- left or right, but not both (keyboard)
updateFrame ((C.cLeft ctl || C.cRight ctl) && (C.cLeft ctl /= C.cRight ctl)) e
+processSpawn :: S.SpriteSheet -> Spawn -> IO Entity
+processSpawn sprites (DustEffectSpawn x y) = mkEffect sprites x y "dust"
+
+update :: S.SpriteSheet -> [Entity] -> IO [Entity]
+update sprites entities = do
+ updated <- traverse (\e -> eUpdate e e) entities
+ new <- traverse (processSpawn sprites) (concatMap eSpawns updated)
+ pure $ map (\e -> e {eSpawns = []}) (filter (not . eDestroy) updated) ++ new
+
render :: SDL.Renderer -> Entity -> IO ()
render renderer ent =
S.render renderer sp x y set frame