diff --git a/fcore/enemy-behaviour.sml b/fcore/enemy-behaviour.sml index 90e575e..dc8f29a 100644 --- a/fcore/enemy-behaviour.sml +++ b/fcore/enemy-behaviour.sml @@ -244,85 +244,15 @@ struct end fun getMoveRightPatches (nextPlatform, enemy, platformTree, acc) = - let - val {x = platX, y = platY, width = platWidth, ...} = nextPlatform - val platFinishX = platX + platWidth - - 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 + if TraceJump.traceRightJump (enemy, #id nextPlatform, platformTree, nextPlatform) then + if standingOnArea (enemy, platformTree) then + EnemyPatch.W_Y_AXIS (JUMPING 0) :: EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc else - (* platform is below or at same y coordinat as enemy - * so might possibly require dropping below rather than jumping. *) - let - (* check if we can get to next platform without jumping. - * If we can, then simply move rightwards - * 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 + EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc + else + (* placeholder: should check if we can move to the next platform while + * dropping *) + EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc fun getMoveLeftPatches (nextPlatform, enemy, platformTree, acc) = let diff --git a/fcore/quad-tree-fold.sml b/fcore/quad-tree-fold.sml index ca15a66..9947bfa 100644 --- a/fcore/quad-tree-fold.sml +++ b/fcore/quad-tree-fold.sml @@ -33,7 +33,7 @@ struct else state in - foldRegionVec (rx, ry, rh, rh, env, state, pos + 1, elements) + foldRegionVec (rx, ry, rw, rh, env, state, pos + 1, elements) end fun foldRegion (rx, ry, rw, rh, env, state, tree) = diff --git a/fcore/trace-jump.sml b/fcore/trace-jump.sml new file mode 100644 index 0000000..364a57c --- /dev/null +++ b/fcore/trace-jump.sml @@ -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 diff --git a/oms.mlb b/oms.mlb index d8547de..bd04d07 100644 --- a/oms.mlb +++ b/oms.mlb @@ -28,6 +28,7 @@ fcore/physics.sml fcore/path-finding.sml +fcore/trace-jump.sml fcore/enemy-behaviour.sml fcore/enemy.sml fcore/player.sml