From 9ffa3f57067598acfbe5196a4452b225ab295b83 Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Wed, 19 Apr 2023 23:16:22 +0100 Subject: Added "runner" enemy --- src/Game/Entities/Runner.hs | 86 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/Game/Entities/Runner.hs (limited to 'src/Game/Entities/Runner.hs') diff --git a/src/Game/Entities/Runner.hs b/src/Game/Entities/Runner.hs new file mode 100644 index 0000000..7d969a5 --- /dev/null +++ b/src/Game/Entities/Runner.hs @@ -0,0 +1,86 @@ +module Game.Entities.Runner (mkRunner) where + +import Data.Bits (Bits (..)) +import Game.Entities.Common +import Game.Entities.Const +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 + s <- S.get sprites "runner" + pure + Entity + { typ = TypeEnemy, + x = x, + y = y, + delay = frameDelay, + frame = 0, + set = toSpriteSet d, + jumping = False, + gravity = gravityOff, + dir = d, + sprite = s, + update = updateRunner playerCollision isBlocked, + destroy = False, + actions = [], + dat = RunnerData 0 + } + +updateRunner :: Collision -> IsBlocked -> Entity -> IO Entity +updateRunner touchedPlayer isBlocked e = do + touched <- touchedPlayer e + if touched + then pure e {actions = [ActionHitPlayer]} + else do + let gravityUpdated = updateGravity isBlocked e + if gravityUpdated.gravity /= gravityOff then pure gravityUpdated else updateMovement $ updateFrame True gravityUpdated + where + updateMovement :: Entity -> IO Entity + 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)) = + 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)) = + tryJumpingOrTurn ent + | ent.dir == DirRight = pure ent {x = ent.x + 1} + | otherwise = pure ent + + 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 + r <- randomRIO (0, length randomWallCount - 1) :: IO Int + pure + ent + { dir = turn ent.dir, + set = toSpriteSet $ turn ent.dir, + y = e.y + 1, + gravity = gravityDown, + frame = jumpFrame, + dat = RunnerData $ randomWallCount !! r + } + | ent.dat.wallCount > 1 && not (isBlocked (ent.x + 8) (ent.y - 1)) && isBlocked (ent.x + 8) ent.y = do + r <- randomRIO (0, length randomWallCount - 1) :: IO Int + pure + ent + { dir = turn ent.dir, + set = toSpriteSet $ turn ent.dir, + gravity = gravityUp, + frame = jumpFrame, + actions = [ActionAddEffect ent.x (ent.y + 8) "dust"], + dat = RunnerData $ randomWallCount !! r + } + | otherwise = + pure + ent + { dir = turn ent.dir, + set = toSpriteSet $ turn ent.dir, + dat = RunnerData (ent.dat.wallCount + 1) + } -- cgit v1.2.3