diff --git a/fcore/enemy-behaviour.sml b/fcore/enemy-behaviour.sml index 3825a2a..a66ca32 100644 --- a/fcore/enemy-behaviour.sml +++ b/fcore/enemy-behaviour.sml @@ -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 :: _ => - getPathToNextPlatform - (nextPlatformID, platforms, platformTree, enemy, eID, pID, acc) + let + val acc = EnemyPatch.W_NEXT_PLAT_ID nextPlatformID :: acc + in + getPathToNextPlatform + (nextPlatformID, platforms, platformTree, enemy, eID, pID, acc) + end | [] => acc end end diff --git a/fcore/enemy-patch.sml b/fcore/enemy-patch.sml index a77a515..dfcdddb 100644 --- a/fcore/enemy-patch.sml +++ b/fcore/enemy-patch.sml @@ -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) = diff --git a/fcore/game-type.sml b/fcore/game-type.sml index 6cb07e8..903708d 100644 --- a/fcore/game-type.sml +++ b/fcore/game-type.sml @@ -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