trace path we can (move right + jump) using quad tree, as it is easier to implement than a pure math based approach

This commit is contained in:
2025-01-29 19:12:24 +00:00
parent a6b04ff98e
commit fac7a81767
4 changed files with 78 additions and 79 deletions

View File

@@ -244,85 +244,15 @@ struct
end end
fun getMoveRightPatches (nextPlatform, enemy, platformTree, acc) = fun getMoveRightPatches (nextPlatform, enemy, platformTree, acc) =
let if TraceJump.traceRightJump (enemy, #id nextPlatform, platformTree, nextPlatform) then
val {x = platX, y = platY, width = platWidth, ...} = nextPlatform if standingOnArea (enemy, platformTree) then
val platFinishX = platX + platWidth EnemyPatch.W_Y_AXIS (JUMPING 0) :: EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc
val {x = ex, y = ey, yAxis = eyAxis, ...} = enemy
val xDiff = platX - ex
in
if ey > platY then
(* enemy is lower than next platform so needs to jump *)
let
val jumpAmt =
case eyAxis of
JUMPING amt => amt
| _ => 0
val apexY = ey - (Constants.jumpLimit - jumpAmt)
(* enemy moves in x and y axis at same rate
* with no acceleration or deceleration.
* So, we can directly compare to see which is lower;
* if x is lower, that means we can't reach if we jump at this point
* but if y is lower, that means we can reach if we jump at this point
* so we should simply move rightwards.
* *)
val yDiff = platY - apexY
in
if yDiff > xDiff then
let
val acc =
if standingOnArea (enemy, platformTree) then
EnemyPatch.W_Y_AXIS (JUMPING 0) :: acc
else
acc
in
EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc
end
else
EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc
end
else else
(* platform is below or at same y coordinat as enemy EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc
* so might possibly require dropping below rather than jumping. *) else
let (* placeholder: should check if we can move to the next platform while
(* check if we can get to next platform without jumping. * dropping *)
* If we can, then simply move rightwards EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc
* and possibly drop below platform.
* Else, jump and move rightwards *)
val yDiff = ey - platY
in
if yDiff >= xDiff then
(* can reach next platform by simply dropping and moving right *)
EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM
:: EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc
else
let
val jumpAmt =
case eyAxis of
JUMPING amt => amt
| _ => 0
val apexY = ey - (Constants.jumpLimit - jumpAmt)
val yDiff = platY - apexY
in
if yDiff >= xDiff then
(* can reach if we jump and move right *)
let
val acc =
if standingOnArea (enemy, platformTree) then
EnemyPatch.W_Y_AXIS (JUMPING 0) :: acc
else
acc
in
EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc
end
else
(* cannot reach yet so move right until we can *)
EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc
end
end
end
fun getMoveLeftPatches (nextPlatform, enemy, platformTree, acc) = fun getMoveLeftPatches (nextPlatform, enemy, platformTree, acc) =
let let

View File

@@ -33,7 +33,7 @@ struct
else else
state state
in in
foldRegionVec (rx, ry, rh, rh, env, state, pos + 1, elements) foldRegionVec (rx, ry, rw, rh, env, state, pos + 1, elements)
end end
fun foldRegion (rx, ry, rw, rh, env, state, tree) = fun foldRegion (rx, ry, rw, rh, env, state, tree) =

68
fcore/trace-jump.sml Normal file
View File

@@ -0,0 +1,68 @@
structure TraceJump =
struct
structure Trace = MakeQuadTreeFold (struct
type env = int
type state = bool
fun fold (foldPlatID, nextPlatID, hasFoundNextPlatID) =
hasFoundNextPlatID orelse foldPlatID = nextPlatID
end)
fun traceRightJumpDescent (x, y, nextPlatID, platTree) =
if x >= Constants.worldWidth orelse y >= Constants.worldHeight then
(* we hit bounds of screen and saw that there was
* no way to jump to next nextPlatID *)
false
else
let
val width = Constants.moveEnemyBy
val height = Constants.worldHeight - y
val shouldJumpRight =
Trace.foldRegion (x, y, width, height, nextPlatID, false, platTree)
val nextX = x + Constants.moveEnemyBy
val nextY = y + Constants.moveEnemyBy
in
shouldJumpRight orelse
traceRightJumpDescent (nextX, nextY, nextPlatID, platTree)
end
fun traceRightJumpAscent (x, y, remainingJump, nextPlatID, platTree, nextPlatform) =
if remainingJump >= Constants.jumpLimit then
false
else
let
val width = Constants.moveEnemyBy
val height = Constants.worldHeight - y
val shouldJumpRight =
Trace.foldRegion (x, y, width, height, nextPlatID, false, platTree)
val nextX = x + Constants.moveEnemyBy
val nextY = y - Constants.moveEnemyBy
val nextJump = remainingJump + Constants.moveEnemyBy
in
shouldJumpRight orelse
traceRightJumpAscent (nextX, nextY, nextJump, nextPlatID, platTree, nextPlatform)
end
fun traceRightJump (enemy, nextPlatID, platTree, nextPlat) =
let
open GameType
val {x, y, ...}: enemy = enemy
in
if EnemyPhysics.standingOnArea (x, y, platTree) then
traceRightJumpAscent (x, y, 0, nextPlatID, platTree, nextPlat)
else
case #yAxis enemy of
JUMPING amt =>
traceRightJumpAscent (x, y, amt, nextPlatID, platTree, nextPlat)
| ON_GROUND =>
traceRightJumpAscent (x, y, 0, nextPlatID, platTree, nextPlat)
| FALLING =>
traceRightJumpDescent (x, y, nextPlatID, platTree)
| DROP_BELOW_PLATFORM =>
traceRightJumpDescent (x, y, nextPlatID, platTree)
| FLOATING _ =>
traceRightJumpDescent (x, y, nextPlatID, platTree)
end
end

View File

@@ -28,6 +28,7 @@ fcore/physics.sml
fcore/path-finding.sml fcore/path-finding.sml
fcore/trace-jump.sml
fcore/enemy-behaviour.sml fcore/enemy-behaviour.sml
fcore/enemy.sml fcore/enemy.sml
fcore/player.sml fcore/player.sml