From 9b7d7a1396e22c2553e0a16a8886d7c7c512b271 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Mon, 27 Jan 2025 23:41:59 +0000 Subject: [PATCH] fix compile errors after previous commit (which involved reimplementing the quad tree to eliminate the possibility of a class of bugs I was experiencing; the problem was that the quad bounds were being passed recursively in different functions, but the long argument list in these functions made it difficult to see where the mismatch was) --- fcore/enemy-behaviour.sml | 142 ++++++++---------- fcore/enemy-patch.sml | 6 +- fcore/enemy.sml | 16 +- fcore/game-type.sml | 24 ++- fcore/physics.sml | 57 ++++--- fcore/platform.sml | 10 +- fcore/player-enemy.sml | 8 +- fcore/player.sml | 9 +- fcore/projectile.sml | 8 +- fcore/quad-tree.sml | 305 ++++++++++++++------------------------ fcore/wall.sml | 10 +- ffi/export.h | 2 + 12 files changed, 264 insertions(+), 333 deletions(-) diff --git a/fcore/enemy-behaviour.sml b/fcore/enemy-behaviour.sml index abf4c51..e1b0505 100644 --- a/fcore/enemy-behaviour.sml +++ b/fcore/enemy-behaviour.sml @@ -8,11 +8,10 @@ struct val searchHeight = 10 val searchWidth = Constants.moveEnemyBy in - QuadHelp.hasCollisionAt - (x, y, searchWidth, searchHeight, wallTree) + QuadTree.hasCollisionAt (x, y, searchWidth, searchHeight, ~1, wallTree) orelse - QuadHelp.hasCollisionAt - (x, y, searchWidth, searchHeight, platformTree) + QuadTree.hasCollisionAt + (x, y, searchWidth, searchHeight, ~1, platformTree) end (* same function takes either wallTree or platformTree and returns true @@ -29,7 +28,7 @@ struct val width = Constants.enemySize val height = Platform.platHeight in - QuadHelp.hasCollisionAt (ex, ey, width, height, tree) + QuadTree.hasCollisionAt (ex, ey, width, height, ~1, tree) end fun getPatrollPatches (enemy: enemy, wallTree, platformTree, acc) = @@ -62,22 +61,17 @@ struct val searchWidth = Constants.moveEnemyBy val searchHeight = Constants.enemySize - 5 - val hasWallAhead = QuadHelp.hasCollisionAt - ( searchStartX - , y - , searchWidth - , searchHeight - , wallTree - ) + val hasWallAhead = QuadTree.hasCollisionAt + (searchStartX, y, searchWidth, searchHeight, ~1, wallTree) in - if - hasWallAhead - then EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc - else if canWalkAhead (searchStartX, y, wallTree, platformTree) then + if hasWallAhead then + EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc + else if canWalkAhead (searchStartX, y, wallTree, platformTree) then (* invert direction if moving further left - * will result in falling down *) + * will result in falling down *) acc - else EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc + else + EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc end | MOVE_RIGHT => let @@ -88,22 +82,17 @@ struct val searchWidth = Constants.moveEnemyBy val searchHeight = Constants.enemySize - 5 - val hasWallAhead = QuadHelp.hasCollisionAt - ( searchStartX - , y - , searchWidth - , searchHeight - , wallTree - ) + val hasWallAhead = QuadTree.hasCollisionAt + (searchStartX, y, searchWidth, searchHeight, ~1, wallTree) in - if - hasWallAhead - then EnemyPatch.W_X_AXIS MOVE_LEFT :: acc - else if canWalkAhead (searchStartX, y, wallTree, platformTree) then + if hasWallAhead then + EnemyPatch.W_X_AXIS MOVE_LEFT :: acc + else if canWalkAhead (searchStartX, y, wallTree, platformTree) then (* invert direction if moving further right - * will result in falling down *) + * will result in falling down *) acc - else EnemyPatch.W_X_AXIS MOVE_LEFT :: acc + else + EnemyPatch.W_X_AXIS MOVE_LEFT :: acc end | STAY_STILL => acc end @@ -119,9 +108,9 @@ struct in (* platY < highestY is correct because lowest number = highest * in * this case *) - if platY < highestY andalso checkY <= platY then + if platY < highestY andalso checkY <= platY then getHighestPlatform (tl, platforms, platY, id, checkY) - else + else getHighestPlatform (tl, platforms, highestY, highestID, checkY) end | [] => highestID @@ -133,8 +122,8 @@ struct val searchWidth = Constants.playerSize val searchHeight = Constants.worldHeight - y - val collisions = QuadHelp.getCollisions - (x, y, searchWidth, searchHeight, platformTree) + val collisions = QuadTree.getCollisions + (x, y, searchWidth, searchHeight, ~1, platformTree) val checkY = y + Constants.playerSize val wh = Constants.worldHeight @@ -151,8 +140,8 @@ struct val y = y + Constants.enemySize - val collisions = QuadHelp.getCollisions - (x, y, searchWidth, searchHeight, platformTree) + val collisions = QuadTree.getCollisions + (x, y, searchWidth, searchHeight, ~1, platformTree) val wh = Constants.worldHeight in getHighestPlatform (collisions, platforms, wh, ~1, y) @@ -191,12 +180,12 @@ struct ON_GROUND => EnemyPatch.W_Y_AXIS (JUMPING 0) :: acc | FALLING => EnemyPatch.W_Y_AXIS (JUMPING 0) :: acc | _ => acc - else - (* have to travel either left or right before jumping *) - if ecx < platX then - EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc - else - EnemyPatch.W_X_AXIS MOVE_LEFT :: acc + else (* have to travel either left or right before jumping *) if + ecx < platX + then + EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc + else + EnemyPatch.W_X_AXIS MOVE_LEFT :: acc else acc end @@ -234,12 +223,12 @@ struct ON_GROUND => EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM :: acc | FALLING => EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM :: acc | _ => acc - else - (* have to travel either left or right before jumping *) - if ecx < platX then - EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc - else - EnemyPatch.W_X_AXIS MOVE_LEFT :: acc + else (* have to travel either left or right before jumping *) if + ecx < platX + then + EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc + else + EnemyPatch.W_X_AXIS MOVE_LEFT :: acc else acc end @@ -282,7 +271,7 @@ struct EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc end else - EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc + EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc end else (* platform is below or at same y coordinat as enemy @@ -296,8 +285,8 @@ struct 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 + EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM + :: EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc else let val jumpAmt = @@ -356,7 +345,7 @@ struct EnemyPatch.W_X_AXIS MOVE_LEFT :: acc end else - EnemyPatch.W_X_AXIS MOVE_LEFT :: acc + EnemyPatch.W_X_AXIS MOVE_LEFT :: acc end else (* platform is below or at same y coordinat as enemy @@ -370,8 +359,8 @@ struct 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_LEFT :: acc + EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM + :: EnemyPatch.W_X_AXIS MOVE_LEFT :: acc else let val jumpAmt = @@ -413,7 +402,7 @@ struct getJumpPatches (nextPlatform, platformTree, enemy, acc) else if canDrop then getDropPatches (nextPlatform, platformTree, enemy, acc) - else + else let (* if can neither jump or drop to next platform vertically * then remaining options are either jumping to the right or left. @@ -439,16 +428,14 @@ struct val efx = ex + Constants.enemySize in if isBetween (px, ex, pfx) andalso isBetween (px, efx, pfx) then - acc - else + 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 + if startDiff > endDiff then EnemyPatch.W_X_AXIS MOVE_LEFT :: acc + else EnemyPatch.W_X_AXIS MOVE_RIGHT :: acc end end @@ -471,35 +458,25 @@ struct in if ey < py - 65 then (* set to falling *) - EnemyPatch.W_NEXT_PLAT_ID ~1 :: - EnemyPatch.W_Y_AXIS FALLING :: - acc + 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) + JUMPING _ => getJumpLandingPatches (enemy, newPlatformID, platforms, acc) + | _ => getFallingPatches (enemy, newPlatformID, platforms, acc) - fun getFollowPatches + fun getFollowPatches (player: player, enemy, wallTree, platformTree, platforms, acc) = let (* todo: possibly get pID and eID of player/enemy in a different way *) val pID = getPlatformBelowPlayer (player, platformTree, platforms) - val pID = - if pID = ~1 then - #platID player - else pID + val pID = if pID = ~1 then #platID player else pID val eID = getPlatformBelowEnemy (enemy, platformTree, platforms) - val eID = - if eID = ~1 then - #platID enemy - else eID + val eID = if eID = ~1 then #platID enemy else eID in if eID = ~1 orelse pID = ~1 then (* without checking that neither of these are ~1 @@ -521,7 +498,14 @@ struct val acc = EnemyPatch.W_NEXT_PLAT_ID nextPlatformID :: acc in getPathToNextPlatform - (nextPlatformID, platforms, platformTree, enemy, eID, pID, acc) + ( nextPlatformID + , platforms + , platformTree + , enemy + , eID + , pID + , acc + ) end | [] => getPatrollPatches (enemy, wallTree, platformTree, acc) end diff --git a/fcore/enemy-patch.sml b/fcore/enemy-patch.sml index dfcdddb..ccc2b41 100644 --- a/fcore/enemy-patch.sml +++ b/fcore/enemy-patch.sml @@ -44,10 +44,12 @@ struct case patch of W_HEALTH health => 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 x => + mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) | W_X_AXIS xAxis => 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 y => + mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) | W_Y_AXIS yAxis => mkEnemy (id, health, x, y, xAxis, yAxis, variant, platID, nextPlatID) | W_PLAT_ID platID => diff --git a/fcore/enemy.sml b/fcore/enemy.sml index 6bbcdcc..1c32d6d 100644 --- a/fcore/enemy.sml +++ b/fcore/enemy.sml @@ -4,8 +4,7 @@ struct fun withDefaultYAxis (enemy: enemy) = case #yAxis enemy of - ON_GROUND => - EnemyPatch.withPatch (enemy, EnemyPatch.W_Y_AXIS FALLING) + ON_GROUND => EnemyPatch.withPatch (enemy, EnemyPatch.W_Y_AXIS FALLING) | _ => enemy fun helpExists (pos, id, collisions) = @@ -35,8 +34,8 @@ struct val size = Constants.enemySize - val hasCollision = QuadHelp.hasCollisionAt - (x, y, size, size, projectileTree) + val hasCollision = QuadTree.hasCollisionAt + (x, y, size, size, ~1, projectileTree) in if hasCollision then if health = 1 then @@ -181,12 +180,17 @@ struct val size = Constants.enemySize - val acc = QuadHelp.insert (x, y, size, size, id, acc) + val acc = QuadTree.insert (x, y, size, size, id, acc) in helpGenerateTree (pos + 1, enemyVec, acc) end - fun generateTree enemyVec = helpGenerateTree (0, enemyVec, QuadTree.empty) + fun generateTree enemyVec = + helpGenerateTree + ( 0 + , enemyVec + , QuadTree.create (Constants.worldWidth, Constants.worldHeight) + ) fun helpFind (findNum, vec: enemy vector, low, high) = (* should only be called when we know enemy already exists in vec *) diff --git a/fcore/game-type.sml b/fcore/game-type.sml index ccce201..9b3cfa7 100644 --- a/fcore/game-type.sml +++ b/fcore/game-type.sml @@ -188,10 +188,26 @@ struct val plat18 = {id = 18, x = 155, y = 499, width = 199} val plat19 = {id = 19, x = 155, y = 399, width = 199} val platforms = Vector.fromList - [plat1, plat2, plat3, plat4, plat5, plat6, plat7, plat8, plat9, plat10, - plat11, plat12, plat13 - , plat14, plat15, plat16, plat17, plat18, - plat19] + [ plat1 + , plat2 + , plat3 + , plat4 + , plat5 + , plat6 + , plat7 + , plat8 + , plat9 + , plat10 + , plat11 + , plat12 + , plat13 + , plat14 + , plat15 + , plat16 + , plat17 + , plat18 + , plat19 + ] val platformTree = Platform.generateTree platforms val enemy1 = diff --git a/fcore/physics.sml b/fcore/physics.sml index 22b8027..9540e13 100644 --- a/fcore/physics.sml +++ b/fcore/physics.sml @@ -84,7 +84,7 @@ struct val ww = Constants.worldWidth val wh = Constants.worldHeight in - QuadHelp.hasCollisionAt (x, y, width, height, tree) + QuadTree.hasCollisionAt (x, y, width, height, ~1, tree) end fun standingOnAreaID (x, y, tree) = @@ -109,10 +109,10 @@ struct val wh = Constants.worldHeight val _ = print "START getItemID\n" - val r = - QuadHelp.getItemID (x, y, width, height, tree) + val r = QuadTree.getItemID (x, y, width, height, tree) val _ = print "FINISH getItemID\n" - in r + in + r end fun getWallPatches (x, y, walls, wallTree, acc) = @@ -125,8 +125,7 @@ struct (* check collision with wall to the left *) val acc = let - val leftWallID = QuadHelp.getItemID - (x - 1, y, 1, 1, wallTree) + val leftWallID = QuadTree.getItemID (x - 1, y, 1, 1, wallTree) in if leftWallID <> ~1 then let @@ -144,8 +143,7 @@ struct (* check collision with wall to the right *) val acc = let - val rightWallID = QuadHelp.getItemID - (x + size - 1, y, 1, 1, wallTree) + val rightWallID = QuadTree.getItemID (x + size - 1, y, 1, 1, wallTree) in if rightWallID <> ~1 then let @@ -160,7 +158,7 @@ struct end (* check collision with wall below *) - val downWallID = QuadHelp.getItemID + val downWallID = QuadTree.getItemID (x + moveBy + 1, y + size, 1, 1, wallTree) in if downWallID <> ~1 then @@ -193,22 +191,24 @@ struct val acc = if platID <> ~1 then - (print ("platID: " ^ Int.toString platID ^ "\n"); case yAxis of - JUMPING _ => - (* pass through, allowing player to jump above the platform *) - acc - | _ => - let - (* default case: - * player will land on platform and stay on the ground there. *) - val {y = platY, ...}: GameType.platform = - Vector.sub (platforms, platID - 1) + ( print ("platID: " ^ Int.toString platID ^ "\n") + ; case yAxis of + JUMPING _ => + (* pass through, allowing player to jump above the platform *) + acc + | _ => + let + (* default case: + * player will land on platform and stay on the ground there. *) + val {y = platY, ...}: GameType.platform = + Vector.sub (platforms, platID - 1) - val newY = platY - Fn.entitySize - val acc = Fn.W_Y_AXIS ON_GROUND :: Fn.W_Y newY :: acc - in - acc - end) + val newY = platY - Fn.entitySize + val acc = Fn.W_Y_AXIS ON_GROUND :: Fn.W_Y newY :: acc + in + acc + end + ) else acc @@ -221,11 +221,10 @@ struct * then set new yAxis to FALLING * so we do not drop below any platforms again * *) - if - QuadHelp.hasCollisionAt - (x, y, size, size, platformTree) - then acc - else Fn.W_Y_AXIS FALLING :: acc + if QuadTree.hasCollisionAt (x, y, size, size, ~1, platformTree) then + acc + else + Fn.W_Y_AXIS FALLING :: acc | _ => acc val acc = getWallPatches (x, y, walls, wallTree, acc) diff --git a/fcore/platform.sml b/fcore/platform.sml index fb9ed40..a954396 100644 --- a/fcore/platform.sml +++ b/fcore/platform.sml @@ -11,13 +11,17 @@ struct else let val {id, x, y, width} = Vector.sub (platVec, pos) - val acc = QuadHelp.insert - (x, y, width, platHeight, id, acc) + val acc = QuadTree.insert (x, y, width, platHeight, id, acc) in helpGenerateTree (pos + 1, platVec, acc) end - fun generateTree platVec = helpGenerateTree (0, platVec, QuadTree.empty) + fun generateTree platVec = + helpGenerateTree + ( 0 + , platVec + , QuadTree.create (Constants.worldWidth, Constants.worldHeight) + ) fun helpFind (findNum, vec, low, high) = let diff --git a/fcore/player-enemy.sml b/fcore/player-enemy.sml index f8e79a1..1a483d7 100644 --- a/fcore/player-enemy.sml +++ b/fcore/player-enemy.sml @@ -47,8 +47,8 @@ struct (case attacked of NOT_ATTACKED => let - val enemyCollisions = QuadHelp.getCollisions - (x, y, size, size, enemyTree) + val enemyCollisions = QuadTree.getCollisions + (x, y, size, size, ~1, enemyTree) val player = Player.enemyCollisionReaction @@ -72,8 +72,8 @@ struct if amt = Constants.attackedLimit then (* if reached limit, detect enemies again *) let - val enemyCollisions = QuadHelp.getCollisions - (x, y, size, size, enemyTree) + val enemyCollisions = QuadTree.getCollisions + (x, y, size, size, ~1, enemyTree) val player = Player.exitAttackedAndCheckEnemies diff --git a/fcore/player.sml b/fcore/player.sml index b7de862..a14f355 100644 --- a/fcore/player.sml +++ b/fcore/player.sml @@ -320,8 +320,9 @@ struct let val player = #player game - val _ = print ("(playerX, playerY) = (" ^Int.toString (#x player) ^ ", " ^ - Int.toString (#y player) ^ ")\n") + val _ = print + ("(playerX, playerY) = (" ^ Int.toString (#x player) ^ ", " + ^ Int.toString (#y player) ^ ")\n") val patches = getProjectilePatches player val player = PlayerPatch.withPatches (player, patches) @@ -430,8 +431,8 @@ struct val ww = Constants.worldWidth val wh = Constants.worldHeight - val enemyCollisions = QuadHelp.getCollisions - (x, y, size, size, enemyTree) + val enemyCollisions = QuadTree.getCollisions + (x, y, size, size, ~1, enemyTree) in Vector.fromList enemyCollisions end diff --git a/fcore/projectile.sml b/fcore/projectile.sml index 813af4d..f4bb28a 100644 --- a/fcore/projectile.sml +++ b/fcore/projectile.sml @@ -11,13 +11,17 @@ struct val size = projectileSizeInt val {x, y, facing = _} = Vector.sub (projectiles, pos) - val acc = QuadHelp.insert (x, y, size, size, pos, acc) + val acc = QuadTree.insert (x, y, size, size, pos, acc) in helpGenerateTree (pos + 1, projectiles, acc) end fun generateTree projectiles = - helpGenerateTree (0, projectiles, QuadTree.empty) + helpGenerateTree + ( 0 + , projectiles + , QuadTree.create (Constants.worldWidth, Constants.worldHeight) + ) fun helpGetProjectileVec (pos, projectiles, width, height, ratio, xOffset, yOffset, acc) = diff --git a/fcore/quad-tree.sml b/fcore/quad-tree.sml index 5674ba0..9e3a58b 100644 --- a/fcore/quad-tree.sml +++ b/fcore/quad-tree.sml @@ -8,21 +8,15 @@ sig | QUERY_ON_RIGHT_SIDE | QUERY_ON_BOTTOM_SIDE - val insert: int * int * int * int * - int * t -> t + val insert: int * int * int * int * int * t -> t - val getCollisions: int * int * int * int * - int * t -> int list + val getCollisions: int * int * int * int * int * t -> int list - val helpGetCollisions: int * int * int * int * - int * int list * t - -> int list + val helpGetCollisions: int * int * int * int * int * int list * t -> int list - val hasCollisionAt: int * int * int * int * - int * t -> bool + val hasCollisionAt: int * int * int * int * int * t -> bool - val getItemID: int * int * int * int * - t -> int + val getItemID: int * int * int * int * t -> int val create: int * int -> t end @@ -34,29 +28,20 @@ struct type item = QuadTreeType.item fun create (width, height) = - LEAF { - items = Vector.fromList [], - x = 0, - y = 0, - w = width, - h = height - } + LEAF {items = Vector.fromList [], x = 0, y = 0, w = width, h = height} fun isColliding (ix, iy, ifx, ify, cx, cy, cfx, cfy) = - ix < cfx andalso - ifx > cx andalso - iy < cfy andalso - ify > cy + ix < cfx andalso ifx > cx andalso iy < cfy andalso ify > cy fun isCollidingPlus (ix, iy, iw, ih, cx, cy, cw, ch) = - let - val ifx = ix + iw - val ify = iy + ih - val cfx = cx + cw - val cfy = cy + ch - in - isColliding (ix, iy, ifx, ify, cx, cy, cfx, cfy) - end + let + val ifx = ix + iw + val ify = iy + ih + val cfx = cx + cw + val cfy = cy + ch + in + isColliding (ix, iy, ifx, ify, cx, cy, cfx, cfy) + end fun visitTopLeft (iX, iY, iW, iH, qX, qY, qW, qH) = let @@ -82,7 +67,7 @@ struct val ifx = iX + iW val ify = iY + iH - + val qmx = qX + hw val qmy = qY + hh @@ -99,7 +84,7 @@ struct val ifx = iX + iW val ify = iY + iH - + val qmx = qX + hw val qmy = qY + hh @@ -116,7 +101,7 @@ struct val ifx = iX + iW val ify = iY + iH - + val qmx = qX + hw val qmy = qY + hh @@ -145,13 +130,7 @@ struct val hw = w div 2 val hh = h div 2 in - LEAF { - items = items, - x = x, - y = y, - w = hw, - h = hh - } + LEAF {items = items, x = x, y = y, w = hw, h = hh} end fun mkTopRight (x, y, w, h, items) = @@ -161,13 +140,7 @@ struct val hh = h div 2 val x = x + hw in - LEAF { - items = items, - x = x, - y = y, - w = hw, - h = hh - } + LEAF {items = items, x = x, y = y, w = hw, h = hh} end fun mkBottomLeft (x, y, w, h, items) = @@ -177,13 +150,7 @@ struct val hh = h div 2 val y = y + hh in - LEAF { - items = items, - x = x, - y = y, - w = hw, - h = hh - } + LEAF {items = items, x = x, y = y, w = hw, h = hh} end fun mkBottomRight (x, y, w, h, items) = @@ -194,17 +161,21 @@ struct val x = x + hw val y = y + hh in - LEAF { - items = items, - x = x, - y = y, - w = hw, - h = hh - } + LEAF {items = items, x = x, y = y, w = hw, h = hh} end - fun splitLeaf (x, y, w, h, tl: item list, tr: item list, bl: item list, br: - item list, elements, pos) = + fun splitLeaf + ( x + , y + , w + , h + , tl: item list + , tr: item list + , bl: item list + , br: item list + , elements + , pos + ) = if pos < 0 then let val tl = mkTopLeft (x, y, w, h, tl) @@ -247,22 +218,29 @@ struct fun insert (iX, iY, iW, iH, itemID, tree: t) = case tree of NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => - if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then - let - (* we are not necessarily inserting into all nodes. - * If isCollidingPlus returns false recursively, - * we return the same node back. *) - val tl = insert (iX, iY, iW, iH, itemID, topLeft) - val tr = insert (iX, iY, iW, iH, itemID, topRight) - val bl = insert (iX, iY, iW, iH, itemID, bottomLeft) - val br = insert (iX, iY, iW, iH, itemID, bottomRight) - in - NODE {topLeft = tl, topRight = tr, bottomLeft = bl, bottomRight = br - , x = x, y = y, w = w, h = h - } - end - else - tree + if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then + let + (* we are not necessarily inserting into all nodes. + * If isCollidingPlus returns false recursively, + * we return the same node back. *) + val tl = insert (iX, iY, iW, iH, itemID, topLeft) + val tr = insert (iX, iY, iW, iH, itemID, topRight) + val bl = insert (iX, iY, iW, iH, itemID, bottomLeft) + val br = insert (iX, iY, iW, iH, itemID, bottomRight) + in + NODE + { topLeft = tl + , topRight = tr + , bottomLeft = bl + , bottomRight = br + , x = x + , y = y + , w = w + , h = h + } + end + else + tree | LEAF {items, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then if Vector.length items + 1 > maxSize then @@ -284,18 +262,7 @@ struct val br = if vbr then [item] else [] in - splitLeaf - ( x - , y - , w - , h - , tl - , tr - , bl - , br - , items - , pos - ) + splitLeaf (x, y, w, h, tl, tr, bl, br, items, pos) end else (* can insert itemID in items vector *) @@ -305,19 +272,23 @@ struct in LEAF {items = items, x = x, y = y, w = w, h = h} end - else + else (* bounds of new item don't fit inside leaf so return old tree *) tree fun isColliding (iX, iY, iW, iH, itemID, checkWith: item) = let - val {itemID = checkID, startX = cX, startY = cY, width = cW, height = cH, ...} = checkWith + val + { itemID = checkID + , startX = cX + , startY = cY + , width = cW + , height = cH + , ... + } = checkWith in - iX < cX + cW andalso - iX + iW > cX andalso - iY < cY + cH andalso - iY + iH > cY andalso - itemID <> checkID + iX < cX + cW andalso iX + iW > cX andalso iY < cY + cH + andalso iY + iH > cY andalso itemID <> checkID end fun getCollisionsVec (iX, iY, iW, iH, itemID, pos, elements, acc) = @@ -338,93 +309,46 @@ struct NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then let - val acc = getCollisionsAll - (iX, iY, iW, iH, itemID, acc, topLeft) + val acc = getCollisionsAll (iX, iY, iW, iH, itemID, acc, topLeft) - val acc = getCollisionsAll - (iX, iY, iW, iH, itemID, acc, topRight) + val acc = getCollisionsAll (iX, iY, iW, iH, itemID, acc, topRight) - val acc = getCollisionsAll - (iX, iY, iW, iH, itemID, acc, bottomLeft) + val acc = getCollisionsAll (iX, iY, iW, iH, itemID, acc, bottomLeft) in - getCollisionsAll - (iX, iY, iW, iH, itemID, acc, bottomRight) + getCollisionsAll (iX, iY, iW, iH, itemID, acc, bottomRight) end else acc | LEAF {items, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then getCollisionsVec (iX, iY, iW, iH, itemID, 0, items, acc) - else acc - - fun helpGetCollisions - ( iX - , iY - , iW - , iH - , itemID - , acc - , tree: t - ) = - case tree of - NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => - if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then - let - val acc = - helpGetCollisions - (iX, iY, iW, iH, itemID, acc, topLeft) - - val acc = - helpGetCollisions - (iX, iY, iW, iH, itemID, acc, topRight) - - val acc = - helpGetCollisions - ( iX - , iY - , iW - , iH - , itemID - , acc - , bottomLeft - ) - in - helpGetCollisions - ( iX - , iY - , iW - , iH - , itemID - , acc - , bottomRight - ) - end - else - acc - | LEAF {items, x, y, w, h} => - if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then - getCollisionsVec - (iX, iY, iW, iH, itemID, 0, items, acc) else acc - fun getCollisions - ( itemX - , itemY - , itemWidth - , itemHeight - , itemID - , tree - ) = - helpGetCollisions - ( itemX - , itemY - , itemWidth - , itemHeight - , itemID - , [] - , tree - ) + fun helpGetCollisions (iX, iY, iW, iH, itemID, acc, tree: t) = + case tree of + NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => + if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then + let + val acc = helpGetCollisions (iX, iY, iW, iH, itemID, acc, topLeft) + + val acc = helpGetCollisions (iX, iY, iW, iH, itemID, acc, topRight) + + val acc = helpGetCollisions + (iX, iY, iW, iH, itemID, acc, bottomLeft) + in + helpGetCollisions (iX, iY, iW, iH, itemID, acc, bottomRight) + end + else + acc + | LEAF {items, x, y, w, h} => + if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then + getCollisionsVec (iX, iY, iW, iH, itemID, 0, items, acc) + else + acc + + fun getCollisions (itemX, itemY, itemWidth, itemHeight, itemID, tree) = + helpGetCollisions (itemX, itemY, itemWidth, itemHeight, itemID, [], tree) (* no variant to represent 'no collision' case * because caller should only try getting collision side @@ -481,38 +405,25 @@ struct let val item = Vector.sub (elements, pos) in - isColliding (iX, iY, iW, iH, itemID, item) orelse - hasCollisionAtVec (iX, iY, iW, iH, itemID, pos + 1, elements) + isColliding (iX, iY, iW, iH, itemID, item) + orelse hasCollisionAtVec (iX, iY, iW, iH, itemID, pos + 1, elements) end - fun hasCollisionAt - ( iX - , iY - , iW - , iH - , itemID - , tree - ) = + fun hasCollisionAt (iX, iY, iW, iH, itemID, tree) = case tree of NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then - hasCollisionAt - (iX, iY, iW, iH, itemID, topLeft) - orelse - hasCollisionAt - (iX, iY, iW, iH, itemID, topRight) - orelse - hasCollisionAt - (iX, iY, iW, iH, itemID, bottomLeft) - orelse - hasCollisionAt - (iX, iY, iW, iH, itemID, bottomRight) - else + hasCollisionAt (iX, iY, iW, iH, itemID, topLeft) + orelse hasCollisionAt (iX, iY, iW, iH, itemID, topRight) + orelse hasCollisionAt (iX, iY, iW, iH, itemID, bottomLeft) + orelse hasCollisionAt (iX, iY, iW, iH, itemID, bottomRight) + else false | LEAF {items, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then hasCollisionAtVec (iX, iY, iW, iH, itemID, 0, items) - else false + else + false fun getItemIDVec (iX, iY, iW, iH, pos, elements) = if pos = Vector.length elements then @@ -545,7 +456,7 @@ struct end else ~1 - | LEAF {items, x, y, w, h} => + | LEAF {items, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then getItemIDVec (iX, iY, iW, iH, 0, items) else diff --git a/fcore/wall.sml b/fcore/wall.sml index e558937..fbbea24 100644 --- a/fcore/wall.sml +++ b/fcore/wall.sml @@ -6,13 +6,17 @@ struct else let val {id, x, y, width, height} = Vector.sub (wallVec, pos) - val acc = QuadHelp.insert - (x, y, width, height, id, acc) + val acc = QuadTree.insert (x, y, width, height, id, acc) in helpGenerateTree (pos + 1, wallVec, acc) end - fun generateTree wallVec = helpGenerateTree (0, wallVec, QuadTree.empty) + fun generateTree wallVec = + helpGenerateTree + ( 0 + , wallVec + , QuadTree.create (Constants.worldWidth, Constants.worldHeight) + ) fun helpGetDrawVecWider (pos, wallVec, acc, winWidth, winHeight, ratio, yOffset) = diff --git a/ffi/export.h b/ffi/export.h index b7a07c9..9c2eec7 100644 --- a/ffi/export.h +++ b/ffi/export.h @@ -157,6 +157,8 @@ typedef Pointer Objptr; extern "C" { #endif +MLLIB_PUBLIC(void mltonKeyCallback (Int32 x0, Int32 x1, Int32 x2, Int32 x3);) +MLLIB_PUBLIC(void mltonFramebufferSizeCallback (Real32 x0, Real32 x1);) #undef MLLIB_PRIVATE #undef MLLIB_PUBLIC