diff --git a/fcore/enemy-behaviour.sml b/fcore/enemy-behaviour.sml index 4dba6da..83a6570 100644 --- a/fcore/enemy-behaviour.sml +++ b/fcore/enemy-behaviour.sml @@ -249,9 +249,8 @@ struct * So, if we check for jump first, we would always jump before dropping * even if jumping is not necessary. *) if TraceJump.traceRightDrop (enemy, #id nextPlatform, platformTree) then - EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM :: - EnemyPatch.W_X_AXIS MOVE_RIGHT :: - acc + EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM :: EnemyPatch.W_X_AXIS MOVE_RIGHT + :: acc else if TraceJump.traceRightJump (enemy, #id nextPlatform, platformTree) then if standingOnArea (enemy, platformTree) then EnemyPatch.W_Y_AXIS (JUMPING 0) :: EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc @@ -261,79 +260,16 @@ struct EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc fun getMoveLeftPatches (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 = ex - platX - 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) - - val yDiff = platY - apexY - in - if yDiff <= xDiff then - (* enemy can reach platform by jumping *) - let - val acc = - if standingOnArea (enemy, platformTree) then - EnemyPatch.W_Y_AXIS (JUMPING 0) :: acc - else - acc - in - EnemyPatch.W_X_AXIS MOVE_LEFT :: acc - end - else - EnemyPatch.W_X_AXIS MOVE_LEFT :: acc - end + if TraceJump.traceLeftDrop (enemy, #id nextPlatform, platformTree) then + EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM :: EnemyPatch.W_X_AXIS MOVE_LEFT + :: acc + else if TraceJump.traceLeftJump (enemy, #id nextPlatform, platformTree) then + if standingOnArea (enemy, platformTree) then + EnemyPatch.W_Y_AXIS (JUMPING 0) :: EnemyPatch.W_X_AXIS MOVE_LEFT :: 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 = platY - ey - in - if yDiff >= xDiff then - (* can reach next platform by simply dropping and moving left *) - EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM - :: EnemyPatch.W_X_AXIS MOVE_LEFT :: 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 left *) - let - val acc = - if standingOnArea (enemy, platformTree) then - EnemyPatch.W_Y_AXIS (JUMPING 0) :: acc - else - acc - in - EnemyPatch.W_X_AXIS MOVE_LEFT :: acc - end - else - (* cannot reach yet so move left until we can *) - EnemyPatch.W_X_AXIS MOVE_LEFT :: acc - end - end - end + EnemyPatch.W_X_AXIS MOVE_LEFT :: acc + else + EnemyPatch.W_X_AXIS MOVE_LEFT :: acc (* get patches to help enemy move to nextPlatformID *) fun getPathToNextPlatform @@ -368,27 +304,26 @@ struct * then move enemy left/right to make them fully overlap with platform *) fun getHorizontalLandingPatches (enemy, nextPlatform, acc) = case #xAxis enemy of - STAY_STILL => - acc + STAY_STILL => acc | _ => - let - val {x = px, width = pw, ...} = nextPlatform - val pfx = px + pw + 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 + 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 @@ -426,16 +361,13 @@ struct case #xAxis enemy of STAY_STILL => let - val acc = - if #x player <= #x enemy then - EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc - else - EnemyPatch.W_X_AXIS MOVE_LEFT :: acc + val acc = + if #x player <= #x enemy then EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc + else EnemyPatch.W_X_AXIS MOVE_LEFT :: acc in acc end - | _ => - getPatrollPatches (enemy, wallTree, platformTree, acc) + | _ => getPatrollPatches (enemy, wallTree, platformTree, acc) fun getFollowPatches (player: player, enemy, wallTree, platformTree, platforms, acc) = @@ -466,8 +398,7 @@ struct nextPlatformID :: _ => let val acc = EnemyPatch.W_NEXT_PLAT_ID nextPlatformID :: acc - val acc = - getPathToNextPlatform + val acc = getPathToNextPlatform ( nextPlatformID , platforms , platformTree @@ -479,7 +410,8 @@ struct in EnemyPatch.W_X_AXIS STAY_STILL :: acc end - | [] => startPatrolPatches (player, enemy, wallTree, platformTree, acc) + | [] => + startPatrolPatches (player, enemy, wallTree, platformTree, acc) end end diff --git a/fcore/game-type.sml b/fcore/game-type.sml index d3dba72..80490b2 100644 --- a/fcore/game-type.sml +++ b/fcore/game-type.sml @@ -168,13 +168,13 @@ struct val walls = Vector.fromList [wall1, wall2, wall3] val wallTree = Wall.generateTree walls - val plat1 = {id = 1, x = 155, y = 911, width = 199} + val plat1 = {id = 1, x = 111, y = 711, width = 199} val plat2 = {id = 2, x = 355, y = 759, width = 555} - val plat3 = {id = 3, x = 355, y = 659, width = 111} - val plat4 = {id = 4, x = 155, y = 855, width = 99} - val plat5 = {id = 5, x = 155, y = 811, width = 199} - val plat6 = {id = 6, x = 155, y = 710, width = 199} - val plat7 = {id = 7, x = 301, y = 855, width = 99} + val plat3 = {id = 3, x = 955, y = 659, width = 111} + val plat4 = {id = 4, x = 455, y = 855, width = 99} + val plat5 = {id = 5, x = 555, y = 811, width = 199} + val plat6 = {id = 6, x = 655, y = 710, width = 199} + val plat7 = {id = 7, x = 701, y = 855, width = 99} val plat8 = {id = 8, x = 970, y = 815, width = 303} val plat9 = {id = 9, x = 959, y = 705, width = 303} val plat10 = {id = 10, x = 970, y = 759, width = 303} @@ -184,9 +184,9 @@ struct val plat14 = {id = 14, x = 1000, y = 415, width = 303} val plat15 = {id = 15, x = 1000, y = 335, width = 303} val plat16 = {id = 16, x = 1000, y = 295, width = 303} - val plat17 = {id = 17, x = 155, y = 599, width = 199} - val plat18 = {id = 18, x = 155, y = 499, width = 199} - val plat19 = {id = 19, x = 155, y = 399, width = 199} + val plat17 = {id = 17, x = 855, y = 599, width = 199} + val plat18 = {id = 18, x = 755, y = 499, width = 199} + val plat19 = {id = 19, x = 655, y = 399, width = 199} val platforms = Vector.fromList [ plat1 , plat2 @@ -212,8 +212,8 @@ struct val enemy1 = { id = 1 - , x = 251 - , y = 855 + , x = 751 + , y = 555 , health = 1 , xAxis = STAY_STILL , yAxis = FALLING diff --git a/fcore/trace-jump.sml b/fcore/trace-jump.sml index 21523f1..82577db 100644 --- a/fcore/trace-jump.sml +++ b/fcore/trace-jump.sml @@ -1,14 +1,16 @@ structure TraceJump = struct - structure Trace = MakeQuadTreeFold (struct - type env = int - type state = bool + structure Trace = + MakeQuadTreeFold + (struct + type env = int + type state = bool - fun fold (foldPlatID, nextPlatID, hasFoundNextPlatID) = - hasFoundNextPlatID orelse foldPlatID = nextPlatID - end) + fun fold (foldPlatID, nextPlatID, hasFoundNextPlatID) = + hasFoundNextPlatID orelse foldPlatID = nextPlatID + end) - fun traceRightJumpDescent (x, y, nextPlatID, platTree) = + fun traceRightDescent (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 *) @@ -17,62 +19,120 @@ struct let val width = Constants.moveEnemyBy val height = Constants.worldHeight - y - val shouldJumpRight = - Trace.foldRegion (x, y, width, height, nextPlatID, false, platTree) + 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) + shouldJumpRight + orelse traceRightDescent (nextX, nextY, nextPlatID, platTree) end - fun traceRightDrop (enemy, nextPlatID, platTree) = + fun traceRightDrop (enemy: GameType.enemy, nextPlatID, platTree) = let - open GameType - val {x, y, ...}: enemy = enemy + val {x, y, ...} = enemy val x = x - Constants.enemySize in - traceRightJumpDescent (x, y, nextPlatID, platTree) + traceRightDescent (x, y, nextPlatID, platTree) end fun traceRightJumpAscent (x, y, remainingJump, nextPlatID, platTree) = if remainingJump >= Constants.jumpLimit then - traceRightJumpDescent (x, y, nextPlatID, platTree) + traceRightDescent (x, y, nextPlatID, platTree) else let val width = Constants.moveEnemyBy val height = Constants.worldHeight - y - val shouldJumpRight = - Trace.foldRegion (x, y, width, height, nextPlatID, false, platTree) + 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 + shouldJumpRight + orelse traceRightJumpAscent (nextX, nextY, nextJump, nextPlatID, platTree) end - fun traceRightJump (enemy, nextPlatID, platTree) = + fun traceRightJump (enemy: GameType.enemy, nextPlatID, platTree) = let - open GameType - val {x, y, ...}: enemy = enemy + val {x, y, ...} = enemy val x = x - Constants.enemySize + + open GameType in if EnemyPhysics.standingOnArea (x, y, platTree) then traceRightJumpAscent (x, y, 0, nextPlatID, platTree) else case #yAxis enemy of - JUMPING amt => - traceRightJumpAscent (x, y, amt, nextPlatID, platTree) - | ON_GROUND => - traceRightJumpAscent (x, y, 0, nextPlatID, platTree) - | FALLING => - traceRightJumpDescent (x, y, nextPlatID, platTree) - | DROP_BELOW_PLATFORM => - traceRightJumpDescent (x, y, nextPlatID, platTree) - | FLOATING _ => - traceRightJumpDescent (x, y, nextPlatID, platTree) + JUMPING amt => traceRightJumpAscent (x, y, amt, nextPlatID, platTree) + | ON_GROUND => traceRightJumpAscent (x, y, 0, nextPlatID, platTree) + | FALLING => traceRightDescent (x, y, nextPlatID, platTree) + | DROP_BELOW_PLATFORM => traceRightDescent (x, y, nextPlatID, platTree) + | FLOATING _ => traceRightDescent (x, y, nextPlatID, platTree) + end + + fun traceLeftDescent (x, y, nextPlatID, platTree) = + if x <= 0 orelse y >= Constants.worldHeight then + false + else + let + val width = Constants.moveEnemyBy + val height = Constants.worldHeight - y + val shouldJumpLeft = Trace.foldRegion + (x, y, width, height, nextPlatID, false, platTree) + + val nextX = x - Constants.moveEnemyBy + val nextY = y + Constants.moveEnemyBy + in + shouldJumpLeft + orelse traceRightDescent (nextX, nextY, nextPlatID, platTree) + end + + fun traceLeftDrop (enemy: GameType.enemy, nextPlatID, platTree) = + let + val {x, y, ...} = enemy + val x = x + Constants.enemySize + in + traceLeftDescent (x, y, nextPlatID, platTree) + end + + fun traceLeftJumpAscent (x, y, remainingJump, nextPlatID, platTree) = + if remainingJump >= Constants.jumpLimit then + traceLeftDescent (x, y, nextPlatID, platTree) + else + let + val width = Constants.moveEnemyBy + val height = Constants.worldHeight - y + val shouldJumpLeft = 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 + shouldJumpLeft + orelse + traceLeftJumpAscent (nextX, nextY, nextJump, nextPlatID, platTree) + end + + fun traceLeftJump (enemy: GameType.enemy, nextPlatID, platTree) = + let + val {x, y, ...} = enemy + val x = x + Constants.enemySize + + open GameType + in + if EnemyPhysics.standingOnArea (x, y, platTree) then + traceLeftJumpAscent (x, y, 0, nextPlatID, platTree) + else + case #yAxis enemy of + JUMPING amt => traceLeftJumpAscent (x, y, amt, nextPlatID, platTree) + | ON_GROUND => traceLeftJumpAscent (x, y, 0, nextPlatID, platTree) + | FALLING => traceLeftDescent (x, y, nextPlatID, platTree) + | DROP_BELOW_PLATFORM => traceLeftDescent (x, y, nextPlatID, platTree) + | FLOATING _ => traceLeftDescent (x, y, nextPlatID, platTree) end end