From 0367b3a23c73d5e8190d2a90eab270eaa14a94ce Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Sat, 11 Jan 2025 13:45:29 +0000 Subject: [PATCH] progress detecting collision between enemy and player's projectile, and decrementing enemy's health once detected --- fcore/game-type.sml | 6 ++-- fcore/game-update.sml | 12 +++++--- fcore/player-enemy.sml | 46 +++++++++++++--------------- fcore/player.sml | 1 + fcore/projectile-enemy.sml | 61 ++++++++++++++++++++++++++++++++++++++ fcore/quad-tree.sml | 5 ++++ oms.mlb | 1 + 7 files changed, 100 insertions(+), 32 deletions(-) create mode 100644 fcore/projectile-enemy.sml diff --git a/fcore/game-type.sml b/fcore/game-type.sml index 190aac8..76612a9 100644 --- a/fcore/game-type.sml +++ b/fcore/game-type.sml @@ -181,9 +181,9 @@ struct val platforms = Vector.fromList [plat1] val platformTree = Platform.generateTree platforms - val enemy1 = {id = 1, x = 300, y = 945, health = 5} - val enemy2 = {id = 2, x = 555, y = 945, health = 5} - val enemy3 = {id = 3, x = 979, y = 945, health = 5} + val enemy1 = {id = 1, x = 300, y = 945, health = 2} + val enemy2 = {id = 2, x = 555, y = 945, health = 2} + val enemy3 = {id = 3, x = 979, y = 945, health = 2} val enemies = Vector.fromList [enemy1, enemy2, enemy3] val enemyTree = Enemy.generateTree enemies in diff --git a/fcore/game-update.sml b/fcore/game-update.sml index 4f6c882..815cbcc 100644 --- a/fcore/game-update.sml +++ b/fcore/game-update.sml @@ -7,11 +7,15 @@ struct val player = Player.runPhysicsAndInput (game, input) - (* check player-enemy collisions and react *) - val (player, enemies) = PlayerEnemy.checkCollisions (player, game) - - (* create enemy quad tree from list of new enemies *) + (* check and react to enemy collisions with player projectile *) + val enemies = + ProjectileEnemy.checkCollisions + (#projectiles player, enemies, enemyTree) val enemyTree = Enemy.generateTree enemies + + (* check player-enemy collisions and react *) + val (player, enemies, enemyTree) = + PlayerEnemy.checkCollisions (player, enemies, enemyTree) in { player = player , walls = walls diff --git a/fcore/player-enemy.sml b/fcore/player-enemy.sml index 5cd7e9c..c0d0552 100644 --- a/fcore/player-enemy.sml +++ b/fcore/player-enemy.sml @@ -47,14 +47,15 @@ struct end | [] => acc - fun checkEnemiesWhileAttacking (player, enemies, lst, acc) = - let - open QuadTree - in - case lst of - enemyID :: tl => (* placeholder *) acc - | [] => acc - end + fun helpExists (pos, id, collisions) = + if pos = Vector.length collisions then + false + else + let val current = Vector.sub (collisions, pos) + in current = id orelse helpExists (pos + 1, id, collisions) + end + + fun exists (id, collisions) = helpExists (0, id, collisions) (* removes enemies from `enemies` vector when that enemy is in collisions *) fun filterEnemyCollisions (pos, collisions, enemies: enemy vector, acc) = @@ -63,19 +64,16 @@ struct else let val enemy = Vector.sub (enemies, pos) + val acc = + if exists (#id enemy, collisions) then (* filter out *) acc + else (* don't filter out *) enemy :: acc in - if BinSearch.exists (#id enemy, collisions) then - (* filter out *) - filterEnemyCollisions (pos - 1, collisions, enemies, acc) - else - (* don't filter out *) - filterEnemyCollisions (pos - 1, collisions, enemies, enemy :: acc) + filterEnemyCollisions (pos - 1, collisions, enemies, acc) end - fun checkCollisions (player, game: game_type) = + fun checkCollisions (player, enemies, enemyTree) = let val {x, y, mainAttack, attacked, ...} = player - val {enemies, enemyTree, ...} = game val size = Player.size in case mainAttack of @@ -86,27 +84,25 @@ struct val y = y - Player.halfSize val size = size * 2 + (* get list of enemies player has collided with *) val enemyCollisions = QuadTree.getCollisions (x, y, size, size, 0, 0, 1920, 1080, 0, enemyTree) - val patches = - checkEnemiesWhileAttacking (player, enemies, enemyCollisions, []) - val player = Player.withPatches (player, patches) + (* filter enemies based on collisions *) val enemyCollisions = Vector.fromList enemyCollisions val enemies = filterEnemyCollisions (Vector.length enemies - 1, enemyCollisions, enemies, []) + val enemyTree = Enemy.generateTree enemies (* add collided enemies to player record, * concatenating with the previous enemies defeated *) val newDefeated = Vector.map (fn id => {angle = 360}) enemyCollisions - val oldDefeated = #enemies player val allDefeated = Vector.concat [oldDefeated, newDefeated] - val player = Player.withPatches (player, [W_ENEMIES allDefeated]) in - (player, enemies) + (player, enemies, enemyTree) end | _ => (case attacked of @@ -119,7 +115,7 @@ struct checkEnemies (player, enemies, enemyCollisions, []) val player = Player.withPatches (player, patches) in - (player, enemies) + (player, enemies, enemyTree) end | ATTACKED amt => if amt = Player.attackedLimit then @@ -132,7 +128,7 @@ struct checkEnemies (player, enemies, enemyCollisions, lst) val player = Player.withPatches (player, patches) in - (player, enemies) + (player, enemies, enemyTree) end else (* if attacked, don't detect collisions, @@ -144,7 +140,7 @@ struct val player = Player.withPatches (player, [W_ATTACKED attacked]) in - (player, enemies) + (player, enemies, enemyTree) end) end end diff --git a/fcore/player.sml b/fcore/player.sml index d06872e..039a680 100644 --- a/fcore/player.sml +++ b/fcore/player.sml @@ -298,6 +298,7 @@ struct val defeatedPi = Real32.Math.pi / 180.0 val defeatedSize = 9.0 val defeatedDistance = 13.0 + val defeatedSizeInt = 9 (* timing variables; always start at 0, * and revert to default state when limit is hit *) diff --git a/fcore/projectile-enemy.sml b/fcore/projectile-enemy.sml new file mode 100644 index 0000000..c2efae6 --- /dev/null +++ b/fcore/projectile-enemy.sml @@ -0,0 +1,61 @@ +structure ProjectileEnemy = +struct + open GameType + + fun helpCheckColisions (pos, projectileTree, enemies, acc) = + if pos < 0 then + Vector.fromList acc + else + let + val enemy = Vector.sub (enemies, pos) + + val {id, health, x, y} = enemy + val size = Enemy.size + + val collisions = QuadTree.helpGetCollisions + (x, y, size, size, 0, 0, 1920, 1080, 0, [], projectileTree) + + (* react to collisions here, possibly removing enemy from acc *) + val acc = + case collisions of + _ :: _ => + if health = 1 then + (* filter enemy out if decrementing their health by 1 + * leads to a health of 0 *) + acc + else + let + (* decrement health by 1 and add to acc *) + val enemy = {id = id, health = health - 1, x = x, y = y} + in + enemy :: acc + end + | [] => enemy :: acc + in + helpCheckColisions (pos - 1, projectileTree, enemies, acc) + end + + fun helpGenerateTree (pos, projectiles, acc) = + if pos = Vector.length projectiles then + acc + else + let + val size = Player.defeatedSizeInt + + val {x, y, facing = _} = Vector.sub (projectiles, pos) + val acc = QuadTree.insert (x, y, size, size, 0, 0, 1920, 1080, pos, acc) + in + helpGenerateTree (pos + 1, projectiles, acc) + end + + fun generateTree projectiles = + helpGenerateTree (0, projectiles, QuadTree.empty) + + fun checkCollisions (projectiles, enemies, enemyTree) = + let + val projectileTree = generateTree projectiles + in + helpCheckColisions + (Vector.length enemies - 1, projectileTree, enemies, []) + end +end diff --git a/fcore/quad-tree.sml b/fcore/quad-tree.sml index 23ab0bc..7495453 100644 --- a/fcore/quad-tree.sml +++ b/fcore/quad-tree.sml @@ -20,6 +20,11 @@ sig int * int * int * int * int * t -> int list + val helpGetCollisions: int * int * int * int * + int * int * int * int * + int * int list * t + -> int list + val getCollisionSides: int * int * int * int * int * int * int * int * int * t -> (collision_side * int) list diff --git a/oms.mlb b/oms.mlb index c016efb..c138858 100644 --- a/oms.mlb +++ b/oms.mlb @@ -18,6 +18,7 @@ fcore/game-type.sml fcore/player.sml +fcore/projectile-enemy.sml fcore/player-enemy.sml fcore/game-update.sml