aboutsummaryrefslogtreecommitdiff
path: root/src/Game/Entities.hs
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-02-17 23:20:31 +0000
committerJuan J. Martinez <jjm@usebox.net>2023-02-17 23:20:31 +0000
commit12728ed582057403e273d593eba781dd8b655f1f (patch)
tree5960174977ba9fd116265b9317c5bea35742b422 /src/Game/Entities.hs
parentcf6fc8b7cb8b108e5778481070944acb13513b5d (diff)
downloadspace-plat-hs-12728ed582057403e273d593eba781dd8b655f1f.tar.gz
space-plat-hs-12728ed582057403e273d593eba781dd8b655f1f.zip
Added fixed pattern enemy (slimes)
Diffstat (limited to 'src/Game/Entities.hs')
-rw-r--r--src/Game/Entities.hs48
1 files changed, 47 insertions, 1 deletions
diff --git a/src/Game/Entities.hs b/src/Game/Entities.hs
index 9152175..f45ae1a 100644
--- a/src/Game/Entities.hs
+++ b/src/Game/Entities.hs
@@ -1,7 +1,9 @@
module Game.Entities (Entities, Entity, mkEntities, updateAll, render) where
+import Data.Bits (Bits (..))
import Data.Foldable (find, traverse_)
import Data.IORef
+import Data.List (sort)
import qualified Game.Controller as C
import qualified Game.Map as M
import qualified Game.Sprites as S
@@ -87,11 +89,12 @@ mkEntities sprites m controls stateRef = do
Just (M.PlayerEntity x y) -> mkPlayer sprites x y controls (M.isBlocked m)
_ -> error "No player entity in map"
playerRef <- newIORef player
- entities <- traverse (toEntity playerRef) $ filter (not . M.isPlayer) (M.objects m)
+ entities <- traverse (toEntity playerRef) $ sort $ filter (not . M.isPlayer) (M.objects m)
-- the entities list has always player first
pure $ Entities sprites playerRef (player : entities)
where
toEntity :: IORef Entity -> M.Object -> IO Entity
+ toEntity playerRef (M.SlimeEntity x y) = mkSlime sprites x y playerRef (M.isBlocked m)
toEntity playerRef (M.BatteryEntity x y) = mkBattery sprites x y playerRef stateRef
toEntity _ (M.PlayerEntity _ _) = error "Player already processed"
@@ -187,6 +190,49 @@ updateBattery touchedPlayer collectedBattery e = do
| e.frame + 1 < frameLimit e = e {delay = frameDelay, frame = e.frame + 1}
| otherwise = e {delay = frameDelay, frame = 0}
+mkSlime :: S.SpriteSheet -> Int -> Int -> IORef Entity -> IsBlocked -> IO Entity
+mkSlime sprites x y playerRef isBlocked = do
+ s <- S.get sprites "slime"
+ pure
+ Entity
+ { typ = TypePickup,
+ x = x,
+ y = y,
+ delay = frameDelay,
+ frame = 0,
+ jumping = False,
+ gravity = gravityOff,
+ dir = DirRight,
+ sprite = s,
+ update = updateSlime (collision playerRef) isBlocked,
+ destroy = False,
+ spawns = []
+ }
+
+updateSlime :: Collision -> IsBlocked -> Entity -> IO Entity
+updateSlime touchedPlayer isBlocked e = do
+ touched <- touchedPlayer e
+ let updated = updateSlimeFrame
+ pure $ if touched then e {destroy = True} else updateMovement updated
+ where
+ updateMovement :: Entity -> Entity
+ updateMovement e'
+ | testBit e'.delay 1 = e'
+ | e'.dir == DirLeft
+ && (isBlocked (e'.x - 1) (e'.y + 15) || isBlocked (e'.x - 1) (e'.y + 10) || not (isBlocked (e'.x - 1) (e'.y + 16))) =
+ e' {dir = DirRight}
+ | e'.dir == DirLeft = e' {x = e'.x - 1}
+ | e'.dir == DirRight
+ && (isBlocked (e'.x + 16) (e'.y + 15) || isBlocked (e'.x + 16) (e'.y + 10) || not (isBlocked (e'.x + 16) (e'.y + 16))) =
+ e' {dir = DirLeft}
+ | e'.dir == DirRight = e' {x = e'.x + 1}
+ | otherwise = e'
+ updateSlimeFrame :: Entity
+ updateSlimeFrame
+ | e.delay > 0 = e {delay = e.delay - 1}
+ | e.frame + 1 < frameLimit e = e {delay = frameDelay + 2, frame = e.frame + 1}
+ | otherwise = e {delay = frameDelay + 2, frame = 0}
+
mkPlayer :: S.SpriteSheet -> Int -> Int -> IORef C.Controls -> IsBlocked -> IO Entity
mkPlayer sprites x y controls isBlocked = do
s <- S.get sprites "player"