From f796f2f858228ce8f7629d837534a2225dd33aeb Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Sat, 18 Jan 2025 00:25:27 +0000 Subject: [PATCH] have functiokn to get upwards path semi-working --- fcore/enemy-behaviour.sml | 164 +++++++++++++++++++++++++++++++++++++- fcore/game-type.sml | 5 +- 2 files changed, 164 insertions(+), 5 deletions(-) diff --git a/fcore/enemy-behaviour.sml b/fcore/enemy-behaviour.sml index f7f9653..70c084d 100644 --- a/fcore/enemy-behaviour.sml +++ b/fcore/enemy-behaviour.sml @@ -131,6 +131,124 @@ struct | STAY_STILL => acc end + (* new pathfinding using quad tree *) + fun getUpwardsPath + (playerPlatID, currentPlatID, platforms, platformTree, dist) = + if playerPlatID = currentPlatID then + (dist, [currentPlatID]) + else + let + val currentPlat = Platform.find (currentPlatID, platforms) + val {x, y, width, ...} = currentPlat + + val searchY = y - Constants.jumpLimit - 1 + val searchH = Constants.jumpLimit + + (* todo: x/width are placeholder values. + * They should define values that let reachable platforms + * on the top left/top right be included in the collision list + * but they currentl are not. *) + val searchX = x + val searchW = width + + val ww = Constants.worldWidth + val wh = Constants.worldHeight + + val upList = QuadTree.getCollisions + (searchX, searchY, searchW, searchH, 0, 0, ww, wh, ~1, platformTree) + + val (bestDist, bestPath) = helpGetUpwardsPath + ( playerPlatID + , platforms + , platformTree + , upList + , dist + , currentPlat + , ~1 + , [] + ) + in + if bestDist = ~1 then + (* invalid; return error value *) + (~1, []) + else + (* is valid, so cons currentPlatID to path *) + (bestDist, currentPlatID :: bestPath) + end + + and helpGetUpwardsPath + ( playerPlatID + , platforms + , platformTree + , lst + , dist + , prevPlat + , bestDist + , bestPath + ) = + case lst of + id :: tl => + let + val currentPlat = Platform.find (id, platforms) + val {y = cy, ...} = currentPlat + val {y = py, ...} = prevPlat + + val diff = py - cy + val platDist = dist + diff + + val (newDist, newPath) = getUpwardsPath + (playerPlatID, id, platforms, platformTree, platDist) + in + if newDist = ~1 then + (* newPath is invalid, so reuse old path *) + helpGetUpwardsPath + ( playerPlatID + , platforms + , platformTree + , tl + , dist + , prevPlat + , bestDist + , bestPath + ) + else if bestDist = ~1 then + (* bestPath is invalid *) + helpGetUpwardsPath + ( playerPlatID + , platforms + , platformTree + , tl + , dist + , prevPlat + , newDist + , newPath + ) + else if newDist < bestDist then + helpGetUpwardsPath + ( playerPlatID + , platforms + , platformTree + , tl + , dist + , prevPlat + , newDist + , newPath + ) + else + helpGetUpwardsPath + ( playerPlatID + , platforms + , platformTree + , tl + , dist + , prevPlat + , bestDist + , bestPath + ) + end + | [] => (bestDist, bestPath) + + (* pathfinding *) fun getHighestPlatform (collisions, platforms, highestY, highestID) = case collisions of id :: tl => @@ -144,7 +262,7 @@ struct end | [] => highestID - fun getPlatformBelowPlayer (player: player, platformTree, platforms) = + fun getPlatformBelowPlayer (player, platformTree, platforms) = let val {x, y, ...} = player @@ -160,6 +278,22 @@ struct getHighestPlatform (collisions, platforms, wh, ~1) end + fun getPlatformBelowEnemy (enemy: enemy, platformTree, platforms) = + let + val {x, y, ...} = enemy + + val searchWidth = Constants.enemySize + val searchHeight = Constants.worldHeight - y + + val ww = Constants.worldWidth + val wh = Constants.worldHeight + + val collisions = QuadTree.getCollisions + (x, y, searchWidth, searchHeight, 0, 0, ww, wh, ~1, platformTree) + in + getHighestPlatform (collisions, platforms, wh, ~1) + end + fun canJumpOnPID (collisions, pID) = case collisions of id :: tl => (id = pID) orelse canJumpOnPID (tl, pID) @@ -171,6 +305,29 @@ struct val {x, y, ...} = enemy + val eID = getPlatformBelowEnemy (enemy, platformTree, platforms) + + val (bestDist, bestPath) = + if eID > ~1 andalso pID > ~1 then + getUpwardsPath (pID, eID, platforms, platformTree, 0) + else + (~1, []) + + val _ = + if bestDist = ~1 then + print "no path\n" + else + let + val _ = print "has path:\n" + val _ = + List.map + (fn platID => + print ("best path platID: " ^ Int.toString platID ^ "\n")) + bestPath + in + () + end + val distance = Constants.moveEnemyBy * Constants.jumpLimit val distance = distance div 2 @@ -193,7 +350,7 @@ struct orelse canJumpOnPID (leftCollisions, pID) end - (* pathfinding *) + fun getFollowPatches (player: player, enemy, wallTree, platformTree, platforms, acc) = let @@ -206,7 +363,6 @@ struct val isOnPlatform = standingOnArea (enemy, platformTree) val hasPlatformAbove = canJumpOnPlatform (player, platforms, enemy, platformTree) - val () = print ("canJump: " ^ Bool.toString hasPlatformAbove ^ "\n") val shouldJump = (isOnWall orelse isOnPlatform) andalso hasPlatformAbove val yAxis = @@ -218,7 +374,7 @@ struct else eyAxis in - EnemyPatch.W_Y_AXIS yAxis :: EnemyPatch.W_X_AXIS xAxis :: acc + EnemyPatch.W_X_AXIS STAY_STILL :: acc end fun getVariantPatches diff --git a/fcore/game-type.sml b/fcore/game-type.sml index af3a16d..a4dae89 100644 --- a/fcore/game-type.sml +++ b/fcore/game-type.sml @@ -164,7 +164,10 @@ struct val plat1 = {id = 1, x = 155, y = 911, width = 199} val plat2 = {id = 2, x = 355, y = 759, width = 555} val plat3 = {id = 3, x = 355, y = 659, width = 555} - val platforms = Vector.fromList [plat1, plat2, plat3] + val plat4 = {id = 4, x = 155, y = 855, width = 199} + val plat5 = {id = 5, x = 155, y = 759, width = 199} + val plat6 = {id = 6, x = 155, y = 610, width = 199} + val platforms = Vector.fromList [plat1, plat2, plat3, plat4, plat5, plat6] val platformTree = Platform.generateTree platforms val enemy1 =