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:
@@ -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
|
||||||
|
|||||||
@@ -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
68
fcore/trace-jump.sml
Normal 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
|
||||||
Reference in New Issue
Block a user