From 54d3f5a32758eb92606338d28a13652bcf51375c Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Tue, 7 Feb 2023 12:10:02 +0000 Subject: Implemented "Coyote time" to make jumping easier --- src/Game/Entities.hs | 55 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/src/Game/Entities.hs b/src/Game/Entities.hs index 66d2da6..b42f232 100644 --- a/src/Game/Entities.hs +++ b/src/Game/Entities.hs @@ -1,5 +1,3 @@ -{-# OPTIONS_GHC -Wno-unused-top-binds #-} - module Game.Entities (Entities, mkEntities, mkPlayer, mkEffect, append, update, render) where import Data.Foldable (traverse_) @@ -29,7 +27,10 @@ gravityUp :: Int gravityUp = 0 gravityDown :: Int -gravityDown = 16 +gravityDown = 14 + +jumpLimit :: Int +jumpLimit = gravityDown + 7 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] @@ -45,6 +46,7 @@ data Entity = Entity eDelay :: Int, eFrame :: Int, eFrameLimit :: Int, + eJumping :: Bool, eGravity :: Int, eDir :: Dir, eSprite :: S.Sprite, @@ -86,7 +88,23 @@ render renderer (Entities _ entities) = do 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 [] + pure $ + Entity + { eType = TypeEffect, + eX = x, + eY = y, + eDelay = frameDelay, + eFrame = 0, + eFrameLimit = 3, + eJumping = False, + eGravity = gravityOff, + eDir = DirRight, + eSprite = s, + eUpdate = pure . updateEffect, + eBlocked = \_ _ -> False, + eDestroy = False, + eSpawns = [] + } updateEffect :: Entity -> Entity updateEffect e @@ -101,7 +119,23 @@ updateEffect 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 + { eType = TypePlayer, + eX = x, + eY = y, + eDelay = 0, + eFrame = 0, + eFrameLimit = 3, + eJumping = False, + eGravity = gravityOff, + eDir = DirRight, + eSprite = s, + eUpdate = updatePlayer controls, + eBlocked = isBlocked, + eDestroy = False, + eSpawns = [] + } updateFrame :: Bool -> Entity -> Entity updateFrame updated e @@ -136,8 +170,12 @@ 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, eSpawns = events ++ [DustEffectSpawn x (y + 8)]} + | not jump + || jumping + -- make jumping easier with "Coyote time" + || (gravity /= gravityOff && (gravity < gravityDown || gravity > jumpLimit)) = + e + | not down = e {eJumping = True, 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 @@ -148,6 +186,7 @@ updateVertical jump down e where x = eX e y = eY e + jumping = eJumping e gravity = eGravity e isBlocked = eBlocked e events = eSpawns e @@ -160,7 +199,7 @@ applyGravity v e && (isBlocked (x + 2) (y + 24) || isBlocked (x + 12) (y + 24)) && not (isBlocked (x + 2) (y + 23)) && not (isBlocked (x + 12) (y + 23)) = - e {eGravity = gravityOff, eDelay = 0} + e {eJumping = False, eGravity = gravityOff, eDelay = 0} | otherwise = applyGravity (v - 1) e {eY = y + change} where gravity = eGravity e -- cgit v1.2.3