From a8091dc3c82a4d646e84b356c46319ba54847ce0 Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Tue, 23 May 2023 21:54:53 +0100 Subject: Add deadly tiles in the blocked layer Currently supported by enemies. --- src/Game/Entities.hs | 4 ++-- src/Game/Entities/Runner.hs | 30 ++++++++++++++++++++++-------- src/Game/Entities/Tracker.hs | 6 +++--- src/Game/Map.hs | 14 +++++++++++++- 4 files changed, 40 insertions(+), 14 deletions(-) (limited to 'src/Game') diff --git a/src/Game/Entities.hs b/src/Game/Entities.hs index 578bf51..bea6e33 100644 --- a/src/Game/Entities.hs +++ b/src/Game/Entities.hs @@ -51,8 +51,8 @@ mkEntities sprites m controls = do toEntity playerRef (M.SlimeEntity x y d) = mkSlime sprites x y d (collision playerRef 16) (M.isBlocked m) toEntity playerRef (M.RobotEntity x y d) = mkRobot sprites x y d (collision playerRef 24) (M.isBlocked m) toEntity playerRef (M.ShooterEntity x y d) = mkShooter sprites x y d (collision playerRef 24) (inLine playerRef 24) (M.isBlocked m) (collision playerRef 8) - toEntity playerRef (M.RunnerEntity x y d) = mkRunner sprites x y d (collision playerRef 24) (M.isBlocked m) - toEntity playerRef (M.TrackerEntity x y d) = mkTracker sprites x y d (collision playerRef 24) (facingLower playerRef) (M.isBlocked m) + toEntity playerRef (M.RunnerEntity x y d) = mkRunner sprites x y d (collision playerRef 24) (M.isBlocked m) (M.isBlockedDeadly m) + toEntity playerRef (M.TrackerEntity x y d) = mkTracker sprites x y d (collision playerRef 24) (facingLower playerRef) (M.isBlocked m) (M.isBlockedDeadly m) toEntity playerRef (M.BatteryEntity x y) = mkBattery sprites x y (collision playerRef 16) toEntity _ (M.PlayerEntity _ _) = error "Player already processed" diff --git a/src/Game/Entities/Runner.hs b/src/Game/Entities/Runner.hs index 7d969a5..288f2b4 100644 --- a/src/Game/Entities/Runner.hs +++ b/src/Game/Entities/Runner.hs @@ -7,8 +7,8 @@ import Game.Entities.Types import qualified Game.Sprites as S import System.Random (randomRIO) -mkRunner :: S.SpriteSheet -> Int -> Int -> Dir -> Collision -> IsBlocked -> IO Entity -mkRunner sprites x y d playerCollision isBlocked = do +mkRunner :: S.SpriteSheet -> Int -> Int -> Dir -> Collision -> IsBlocked -> IsBlocked -> IO Entity +mkRunner sprites x y d playerCollision isBlocked isBlockedDeadly = do s <- S.get sprites "runner" pure Entity @@ -22,14 +22,14 @@ mkRunner sprites x y d playerCollision isBlocked = do gravity = gravityOff, dir = d, sprite = s, - update = updateRunner playerCollision isBlocked, + update = updateRunner playerCollision isBlocked isBlockedDeadly, destroy = False, actions = [], dat = RunnerData 0 } -updateRunner :: Collision -> IsBlocked -> Entity -> IO Entity -updateRunner touchedPlayer isBlocked e = do +updateRunner :: Collision -> IsBlocked -> IsBlocked -> Entity -> IO Entity +updateRunner touchedPlayer isBlocked isBlockedDeadly e = do touched <- touchedPlayer e if touched then pure e {actions = [ActionHitPlayer]} @@ -41,21 +41,35 @@ updateRunner touchedPlayer isBlocked e = do updateMovement ent | testBit ent.delay 1 = pure ent | ent.dir == DirLeft - && (isBlocked (ent.x - 1) (ent.y + 17) || isBlocked (ent.x - 1) (ent.y + 17)) = + && ( isBlocked (ent.x - 1) (ent.y + 17) + || isBlocked (ent.x - 1) (ent.y + 17) + || checkDeadlyFloor (ent.x - 1) (ent.y + 24) + ) = tryJumpingOrTurn ent | ent.dir == DirLeft = pure ent {x = ent.x - 1} | ent.dir == DirRight - && (isBlocked (ent.x + 16) (ent.y + 17) || isBlocked (ent.x + 16) (ent.y + 17)) = + && ( isBlocked (ent.x + 16) (ent.y + 17) + || isBlocked (ent.x + 16) (ent.y + 17) + || checkDeadlyFloor (ent.x + 16) (ent.y + 24) + ) = tryJumpingOrTurn ent | ent.dir == DirRight = pure ent {x = ent.x + 1} | otherwise = pure ent + checkDeadlyFloor :: Int -> Int -> Bool + checkDeadlyFloor x y + | isBlockedDeadly x y = True + | isBlocked x y = False + | otherwise = checkDeadlyFloor x (y + 8) + randomWallCount :: [Int] randomWallCount = [0, 0, 0, 2, 2, 3] tryJumpingOrTurn :: Entity -> IO Entity tryJumpingOrTurn ent - | ent.dat.wallCount > 2 && not (isBlocked (ent.x + 8) (ent.y + 24 + 8)) = do + | ent.dat.wallCount > 2 + && not (isBlocked (ent.x + 8) (ent.y + 24 + 8)) + && not (checkDeadlyFloor (ent.x + 8) (ent.y + 24 + 8)) = do r <- randomRIO (0, length randomWallCount - 1) :: IO Int pure ent diff --git a/src/Game/Entities/Tracker.hs b/src/Game/Entities/Tracker.hs index ef7325f..80b8574 100644 --- a/src/Game/Entities/Tracker.hs +++ b/src/Game/Entities/Tracker.hs @@ -5,10 +5,10 @@ import Game.Entities.Runner import Game.Entities.Types import qualified Game.Sprites as S -mkTracker :: S.SpriteSheet -> Int -> Int -> Dir -> Collision -> Collision -> IsBlocked -> IO Entity -mkTracker sprites x y d playerCollision facingPlayerLower isBlocked = do +mkTracker :: S.SpriteSheet -> Int -> Int -> Dir -> Collision -> Collision -> IsBlocked -> IsBlocked -> IO Entity +mkTracker sprites x y d playerCollision facingPlayerLower isBlocked isBlockedDeadly = do s <- S.get sprites "tracker" - runner <- mkRunner sprites x y d playerCollision isBlocked + runner <- mkRunner sprites x y d playerCollision isBlocked isBlockedDeadly pure runner {sprite = s, update = updateTracker runner.update facingPlayerLower isBlocked} updateTracker :: (Entity -> IO Entity) -> Collision -> IsBlocked -> Entity -> IO Entity diff --git a/src/Game/Map.hs b/src/Game/Map.hs index 29597dd..d585ff6 100644 --- a/src/Game/Map.hs +++ b/src/Game/Map.hs @@ -10,6 +10,7 @@ module Game.Map render, update, isBlocked, + isBlockedDeadly, isPlayer, Viewport (..), viewport, @@ -31,6 +32,9 @@ import Text.JSON.Types frameDelay :: Int frameDelay = 6 +deadlyTileId :: Int +deadlyTileId = 29 + data Tileset = Tileset { cols :: Int, width :: Int, @@ -235,13 +239,21 @@ load filename tex = do _ -> Nothing -- | Check for collision detection vs "Blocked" TileLayer. --- x and y in pixels. +-- x and y in pixels. isBlocked :: Map -> Int -> Int -> Bool isBlocked (Map (MapData mapWidth _ tilesets _ blocked _) _ _) x y = blocked Vector.! ((x `div` ts.width) + (y `div` ts.height) * mapWidth) >= ts.firstGid where ts = Vector.head tilesets +-- | Check for collision detection vs deadly tiles in "Blocked" TileLayer. +-- x and y in pixels. +isBlockedDeadly :: Map -> Int -> Int -> Bool +isBlockedDeadly (Map (MapData mapWidth _ tilesets _ blocked _) _ _) x y = + blocked Vector.! ((x `div` ts.width) + (y `div` ts.height) * mapWidth) == deadlyTileId + ts.firstGid + where + ts = Vector.head tilesets + -- | Return the objects in a map. objects :: Map -> [Object] objects (Map md _ _) = Vector.toList md.objects -- cgit v1.2.3