From bb0cf6bd33e22c4ce96fd9ee3665c9faf4bfcc7a Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Sun, 26 Jan 2025 13:23:20 +0000 Subject: [PATCH] better path landing implemented, making sure enemy fully overlaps platform they are trying to reach, and enemy's jump is clearer (before, when enemy landed on platform, they went straight to the top of the platform, but now they jump a little over the platform which looks clearer) --- fcore/enemy-behaviour.sml | 72 +++++++++++++++++++++++++++++++++++---- fcore/enemy-patch.sml | 21 +++++++----- fcore/game-type.sml | 5 +++ 3 files changed, 84 insertions(+), 14 deletions(-) diff --git a/fcore/enemy-behaviour.sml b/fcore/enemy-behaviour.sml index 3825a2a..a66ca32 100644 --- a/fcore/enemy-behaviour.sml +++ b/fcore/enemy-behaviour.sml @@ -432,8 +432,6 @@ struct val currentPlatform = Platform.find (eID, platforms) val nextPlatform = Platform.find (nextPlatformID, platforms) - val {x = eX, y = ey, yAxis = eyAxis, ...} = enemy - val canJump = canJump (currentPlatform, nextPlatform) val canDrop = canDrop (currentPlatform, nextPlatform) in @@ -446,6 +444,7 @@ struct (* if can neither jump or drop to next platform vertically * then remaining options are either jumping to the right or left. * Figure out which the enemy needs to do and progress to it. *) + val {x = eX, ...} = enemy val {x = nPlatX, width = nPlatW, ...} = nextPlatform in if eX < nPlatX then @@ -455,6 +454,63 @@ struct end end + (* if only one side in x direction overlaps with platform, + * then move enemy left/right to make them fully overlap with platform *) + fun getHorizontalLandingPatches (enemy, nextPlatform, acc) = + let + val {x = px, width = pw, ...} = nextPlatform + val pfx = px + pw + + val {x = ex, ...} = enemy + val efx = ex + Constants.enemySize + in + if isBetween (px, ex, pfx) andalso isBetween (px, efx, pfx) then + acc + else + let + val startDiff = abs (px - ex) + val endDiff = abs (pfx - efx) + in + if startDiff > endDiff then + EnemyPatch.W_X_AXIS MOVE_LEFT :: acc + else + EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc + end + end + + fun getFallingPatches (enemy, newPlatformID, platforms, acc) = + let + val nextPlatform = Platform.find (newPlatformID, platforms) + val acc = getHorizontalLandingPatches (enemy, nextPlatform, acc) + in + EnemyPatch.W_NEXT_PLAT_ID ~1 :: acc + end + + fun getJumpLandingPatches (enemy, nextPlatformID, platforms, acc) = + let + val nextPlatform = Platform.find (nextPlatformID, platforms) + val {y = py, ...} = nextPlatform + + val {y = ey, ...} = enemy + + val acc = getHorizontalLandingPatches (enemy, nextPlatform, acc) + in + if ey < py - 65 then + (* set to falling *) + EnemyPatch.W_NEXT_PLAT_ID ~1 :: + EnemyPatch.W_Y_AXIS FALLING :: + acc + else + acc + end + + fun getLandingPatches (newPlatformID, platforms, enemy, acc) = + case #yAxis enemy of + JUMPING _ => + getJumpLandingPatches (enemy, newPlatformID, platforms, acc) + | _ => + getFallingPatches (enemy, newPlatformID, platforms, acc) + fun canJumpOnPlatform (player, platforms, enemy: enemy, platformTree, acc) = let (* todo: possibly get pID and eID of player/enemy in a different way *) @@ -470,8 +526,8 @@ struct #platID enemy else eID in - if eID = pID then - EnemyPatch.W_Y_AXIS FALLING :: acc + if eID = #nextPlatID enemy then + getLandingPatches (eID, platforms, enemy, acc) else if eID = ~1 orelse pID = ~1 then (* without checking that neither of these are ~1 * (which means there is no platform below the enemy/player) @@ -484,8 +540,12 @@ struct in case bestPath of nextPlatformID :: _ => - getPathToNextPlatform - (nextPlatformID, platforms, platformTree, enemy, eID, pID, acc) + let + val acc = EnemyPatch.W_NEXT_PLAT_ID nextPlatformID :: acc + in + getPathToNextPlatform + (nextPlatformID, platforms, platformTree, enemy, eID, pID, acc) + end | [] => acc end end diff --git a/fcore/enemy-patch.sml b/fcore/enemy-patch.sml index a77a515..dfcdddb 100644 --- a/fcore/enemy-patch.sml +++ b/fcore/enemy-patch.sml @@ -7,6 +7,7 @@ sig | W_X_AXIS of GameType.x_axis | W_Y_AXIS of GameType.y_axis | W_PLAT_ID of int + | W_NEXT_PLAT_ID of int val withPatch: GameType.enemy * enemy_patch -> GameType.enemy @@ -22,8 +23,9 @@ struct | W_X_AXIS of GameType.x_axis | W_Y_AXIS of GameType.y_axis | W_PLAT_ID of int + | W_NEXT_PLAT_ID of int - fun mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID) = + fun mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) = { id = id , health = health , x = x @@ -32,23 +34,26 @@ struct , yAxis = yAxis , variant = variant , platID = platID + , nextPlatID = nextPlatID } fun withPatch (enemy, patch) = let - val {id, health, x, y, xAxis, yAxis, variant, platID} = enemy + val {id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID} = enemy in case patch of W_HEALTH health => - mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID) - | W_X x => mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID) + mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) + | W_X x => mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) | W_X_AXIS xAxis => - mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID) - | W_Y y => mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID) + mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) + | W_Y y => mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) | W_Y_AXIS yAxis => - mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID) + mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) | W_PLAT_ID platID => - mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID) + mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) + | W_NEXT_PLAT_ID nextPlatID => + mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) end fun withPatches (enemy, lst) = diff --git a/fcore/game-type.sml b/fcore/game-type.sml index 6cb07e8..903708d 100644 --- a/fcore/game-type.sml +++ b/fcore/game-type.sml @@ -56,6 +56,7 @@ sig , yAxis: y_axis , variant: EnemyVariants.t , platID: int + , nextPlatID: int } type game_type = @@ -129,6 +130,7 @@ struct , yAxis: y_axis , variant: EnemyVariants.t , platID: int + , nextPlatID: int } type game_type = @@ -189,6 +191,7 @@ struct , yAxis = FALLING , variant = EnemyVariants.FOLLOW_SLIME , platID = ~1 + , nextPlatID = ~1 } val enemy2 = { id = 2 @@ -199,6 +202,7 @@ struct , yAxis = FALLING , variant = EnemyVariants.PATROL_SLIME , platID = ~1 + , nextPlatID = ~1 } val enemy3 = { id = 3 @@ -209,6 +213,7 @@ struct , yAxis = FALLING , variant = EnemyVariants.PATROL_SLIME , platID = ~1 + , nextPlatID = ~1 } val enemies = Vector.fromList [enemy1] in