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)

This commit is contained in:
2025-01-26 13:23:20 +00:00
parent c25afb6f03
commit bb0cf6bd33
3 changed files with 84 additions and 14 deletions

View File

@@ -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 :: _ =>
let
val acc = EnemyPatch.W_NEXT_PLAT_ID nextPlatformID :: acc
in
getPathToNextPlatform
(nextPlatformID, platforms, platformTree, enemy, eID, pID, acc)
end
| [] => acc
end
end

View File

@@ -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) =

View File

@@ -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