From cc2eb419abadbaaa092527dc5e18c4c377fcdc5d Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Fri, 29 Aug 2025 13:55:46 +0100 Subject: [PATCH] use timing information introduced in MAIN_ATTACKING case so that a second attack is required to add a falling enemy to the player's list --- fcore/level/enemy/enemy-type.sml | 4 +- fcore/level/enemy/falling-enemies.sml | 10 +- fcore/level/level-update.sml | 5 +- fcore/level/player/player-attack.sml | 138 ++++++++++++++++---------- 4 files changed, 99 insertions(+), 58 deletions(-) diff --git a/fcore/level/enemy/enemy-type.sml b/fcore/level/enemy/enemy-type.sml index 1964eaa..a5e733a 100644 --- a/fcore/level/enemy/enemy-type.sml +++ b/fcore/level/enemy/enemy-type.sml @@ -22,7 +22,7 @@ sig , shieldOn: bool } - type falling_enemy = {x: int, y: int, variant: variant} + type falling_enemy = {x: int, y: int, variant: variant, time: Time.time} datatype shoot_x_axis = SHOOT_LEFT | SHOOT_RIGHT | NO_SHOOT_X datatype shoot_y_axis = SHOOT_UP | SHOOT_DOWN | NO_SHOOT_Y @@ -52,7 +52,7 @@ struct , shieldOn: bool } - type falling_enemy = {x: int, y: int, variant: variant} + type falling_enemy = {x: int, y: int, variant: variant, time: Time.time} datatype shoot_x_axis = SHOOT_LEFT | SHOOT_RIGHT | NO_SHOOT_X datatype shoot_y_axis = SHOOT_UP | SHOOT_DOWN | NO_SHOOT_Y diff --git a/fcore/level/enemy/falling-enemies.sml b/fcore/level/enemy/falling-enemies.sml index 33f1603..f6c6db1 100644 --- a/fcore/level/enemy/falling-enemies.sml +++ b/fcore/level/enemy/falling-enemies.sml @@ -41,7 +41,7 @@ struct fun fold (fallingID, fallingEnemy, (), fallingMap) = let - val {x, y, variant} = fallingEnemy + val {x, y, variant, time} = fallingEnemy val size = Constants.enemySize val ww = Constants.worldWidth val wh = Constants.worldHeight @@ -49,7 +49,11 @@ struct if Collision.isCollidingPlus (x, y, size, size, 0, 0, ww, wh) then let val newFalling = - {x = x, y = y - Constants.moveEnemyBy, variant = variant} + { x = x + , y = y - Constants.moveEnemyBy + , variant = variant + , time = time + } in FallingEnemyMap.add (fallingID, newFalling, fallingMap) end @@ -81,7 +85,7 @@ struct fun helpGetDrawVec (fallingEnemy, width, height, ratio, xOffset, yOffset, acc) = let - val {x, y, variant = _} = fallingEnemy + val {x, y, variant = _, time = _} = fallingEnemy val x = Real32.fromInt x * ratio + xOffset val y = Real32.fromInt y * ratio + yOffset diff --git a/fcore/level/level-update.sml b/fcore/level/level-update.sml index 524292e..afed9aa 100644 --- a/fcore/level/level-update.sml +++ b/fcore/level/level-update.sml @@ -25,9 +25,8 @@ struct (player, enemies, enemyTree, fallingEnemies) val projectiles = #projectiles player - val (fallingEnemies, enemies) = - PlayerAttack.projectileHitEnemy - (projectiles, enemies, enemyTree, fallingEnemies) + val (fallingEnemies, enemies) = PlayerAttack.projectileHitEnemy + (projectiles, enemies, enemyTree, fallingEnemies, time) val enemies = Enemy.update (enemies, walls, wallTree, platforms, platformTree, player, graph) diff --git a/fcore/level/player/player-attack.sml b/fcore/level/player/player-attack.sml index 2b9e3bb..573b92b 100644 --- a/fcore/level/player/player-attack.sml +++ b/fcore/level/player/player-attack.sml @@ -4,60 +4,78 @@ struct structure PlayerAttackEnemy = MakeQuadTreeFold (struct - type env = unit + type env = Time.time type state = FallingEnemyMap.t * EnemyMap.t open EnemyType - fun defeatEnemy (enemyID, enemyMap, fallingMap) = + fun defeatEnemy (enemyID, enemyMap, fallingMap, time) = case EnemyMap.get (enemyID, enemyMap) of - SOME (enemy: EnemyType.enemy) => - let - val {x, y, variant, ...} = enemy - val fallenEnemy = {x = x, y = y, variant = variant} - val fallingMap = FallingEnemyMap.add (enemyID, fallenEnemy, fallingMap) - val enemyMap = EnemyMap.remove (enemyID, enemyMap) - in - (fallingMap, enemyMap) - end - | NONE => (fallingMap, enemyMap) + SOME (enemy: EnemyType.enemy) => + let + val {x, y, variant, ...} = enemy + val fallenEnemy = + {x = x, y = y, variant = variant, time = time} + val fallingMap = + FallingEnemyMap.add (enemyID, fallenEnemy, fallingMap) + val enemyMap = EnemyMap.remove (enemyID, enemyMap) + in + (fallingMap, enemyMap) + end + | NONE => (fallingMap, enemyMap) - fun shieldSlimeAttacked (enemyID, enemy, enemyMap, fallingMap) = + fun shieldSlimeAttacked (enemyID, enemy, enemyMap, fallingMap, time) = if #shieldOn enemy then (fallingMap, enemyMap) - else defeatEnemy (enemyID, enemyMap, fallingMap) + else defeatEnemy (enemyID, enemyMap, fallingMap, time) - fun onPlayerAttack (enemyID, enemy, enemyMap, fallingMap) = + fun onPlayerAttack (enemyID, enemy, enemyMap, fallingMap, time) = case #variant enemy of - PATROL_SLIME => defeatEnemy (enemyID, enemyMap, fallingMap) - | FOLLOW_SLIME => defeatEnemy (enemyID, enemyMap, fallingMap) - | STRAIGHT_BAT => defeatEnemy (enemyID, enemyMap, fallingMap) + PATROL_SLIME => defeatEnemy (enemyID, enemyMap, fallingMap, time) + | FOLLOW_SLIME => defeatEnemy (enemyID, enemyMap, fallingMap, time) + | STRAIGHT_BAT => defeatEnemy (enemyID, enemyMap, fallingMap, time) | SHIELD_SLIME => - shieldSlimeAttacked (enemyID, enemy, enemyMap, fallingMap) + shieldSlimeAttacked (enemyID, enemy, enemyMap, fallingMap, time) - fun fold (enemyID, (), (fallingMap, enemyMap)) = + fun fold (enemyID, time, (fallingMap, enemyMap)) = case EnemyMap.get (enemyID, enemyMap) of SOME enemy => - onPlayerAttack (enemyID, enemy, enemyMap, fallingMap) + onPlayerAttack (enemyID, enemy, enemyMap, fallingMap, time) | NONE => (fallingMap, enemyMap) end) structure PlayerAttackFalling = MakeQuadTreeFold (struct - type env = unit + type env = Time.time type state = PlayerType.defeated_enemies list * FallingEnemyMap.t - fun fold (fallingID, (), (defeatedList, fallingMap)) = - let - val defeatedList = {angle = 1} :: defeatedList - val fallingMap = FallingEnemyMap.remove (fallingID, fallingMap) - in - (defeatedList, fallingMap) - end + open Time + + fun fold (fallingID, mainAttackTime, (defeatedList, fallingMap)) = + case FallingEnemyMap.get (fallingID, fallingMap) of + SOME {time = fallingStartTime, ...} => + if mainAttackTime > fallingStartTime then + let + val defeatedList = {angle = 1} :: defeatedList + val fallingMap = + FallingEnemyMap.remove (fallingID, fallingMap) + in + (defeatedList, fallingMap) + end + else + (defeatedList, fallingMap) + | NONE => (defeatedList, fallingMap) end) fun helpAttackEnemies - (projectileX, projectileY, enemyMap, enemyTree, fallingMap, player) = + ( projectileX + , projectileY + , enemyMap + , enemyTree + , fallingMap + , player + , mainAttackTime + ) = let val width = Constants.projectileWidth val height = Constants.projectileHeight @@ -68,13 +86,20 @@ struct , projectileY , width , height - , () + , mainAttackTime , ([], fallingMap) , fallingTree ) val (fallingMap, enemyMap) = PlayerAttackEnemy.foldRegion - (projectileX, projectileY, width, height, (), (fallingMap, enemyMap), enemyTree) + ( projectileX + , projectileY + , width + , height + , mainAttackTime + , (fallingMap, enemyMap) + , enemyTree + ) val defeatedList = Vector.fromList defeatedList val defeatedList = Vector.concat [defeatedList, #enemies player] @@ -91,7 +116,7 @@ struct val {x, y, facing, mainAttack, ...} = player in case mainAttack of - MAIN_ATTACKING _ => + MAIN_ATTACKING {timePressed, ...} => (case facing of FACING_RIGHT => let @@ -105,6 +130,7 @@ struct , enemyTree , fallingMap , player + , timePressed ) end | FACING_LEFT => @@ -119,6 +145,7 @@ struct , enemyTree , fallingMap , player + , timePressed ) end) | _ => (player, enemyMap, fallingMap) @@ -128,15 +155,16 @@ struct structure ProjectileHitEnemy = MakeQuadTreeFold (struct - type env = unit + type env = Time.time type state = FallingEnemyMap.t * EnemyMap.t open EnemyType - fun onDefeated (enemyID, enemy, enemyMap, fallingMap) = + fun onDefeated (enemyID, enemy, enemyMap, fallingMap, currentTime) = let val {x, y, variant, ...} = enemy - val fallingItem = {x = x, y = y, variant = variant} + val fallingItem = + {x = x, y = y, variant = variant, time = currentTime} val fallingMap = FallingEnemyMap.add (enemyID, fallingItem, fallingMap) val enemyMap = EnemyMap.remove (enemyID, enemyMap) @@ -144,26 +172,34 @@ struct (fallingMap, enemyMap) end - fun onShieldSlimeAttacked (enemyID, enemy, enemyMap, fallingMap) = + fun onShieldSlimeAttacked + (enemyID, enemy, enemyMap, fallingMap, currentTime) = if #shieldOn enemy then (fallingMap, enemyMap) - else onDefeated (enemyID, enemy, enemyMap, fallingMap) + else onDefeated (enemyID, enemy, enemyMap, fallingMap, currentTime) - fun onProjectileAttack (enemyID, enemy, enemyMap, fallingMap) = + fun onProjectileAttack + (enemyID, enemy, enemyMap, fallingMap, currentTime) = case #variant enemy of - PATROL_SLIME => onDefeated (enemyID, enemy, enemyMap, fallingMap) - | FOLLOW_SLIME => onDefeated (enemyID, enemy, enemyMap, fallingMap) - | STRAIGHT_BAT => onDefeated (enemyID, enemy, enemyMap, fallingMap) + PATROL_SLIME => + onDefeated (enemyID, enemy, enemyMap, fallingMap, currentTime) + | FOLLOW_SLIME => + onDefeated (enemyID, enemy, enemyMap, fallingMap, currentTime) + | STRAIGHT_BAT => + onDefeated (enemyID, enemy, enemyMap, fallingMap, currentTime) | SHIELD_SLIME => - onShieldSlimeAttacked (enemyID, enemy, enemyMap, fallingMap) + onShieldSlimeAttacked + (enemyID, enemy, enemyMap, fallingMap, currentTime) - fun fold (enemyID, (), (fallingMap, enemyMap)) = + fun fold (enemyID, currentTime, (fallingMap, enemyMap)) = case EnemyMap.get (enemyID, enemyMap) of SOME enemy => - onProjectileAttack (enemyID, enemy, enemyMap, fallingMap) + onProjectileAttack + (enemyID, enemy, enemyMap, fallingMap, currentTime) | NONE => (fallingMap, enemyMap) end) - fun helpProjectileHitEnemy (pos, projectiles, enemyTree, enemyMap, fallingMap) = + fun helpProjectileHitEnemy + (pos, projectiles, enemyTree, enemyMap, fallingMap, currentTime) = if pos = Vector.length projectiles then (fallingMap, enemyMap) else @@ -172,12 +208,14 @@ struct Vector.sub (projectiles, pos) val size = Constants.projectileSizeInt val (fallingMap, enemyMap) = ProjectileHitEnemy.foldRegion - (x, y, size, size, (), (fallingMap, enemyMap), enemyTree) + (x, y, size, size, currentTime, (fallingMap, enemyMap), enemyTree) in helpProjectileHitEnemy - (pos + 1, projectiles, enemyTree, enemyMap, fallingMap) + (pos + 1, projectiles, enemyTree, enemyMap, fallingMap, currentTime) end - fun projectileHitEnemy (projectiles, enemyMap, enemyTree, fallingMap) = - helpProjectileHitEnemy (0, projectiles, enemyTree, enemyMap, fallingMap) + fun projectileHitEnemy + (projectiles, enemyMap, enemyTree, fallingMap, currentTime) = + helpProjectileHitEnemy + (0, projectiles, enemyTree, enemyMap, fallingMap, currentTime) end