From c5cea8dcb33b416291c439e6d4785c5400310de2 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Thu, 13 Feb 2025 13:36:30 +0000 Subject: [PATCH] partial refactoring so we use EnemyMap.t for collection of enemies --- fcore/enemy/enemy-map.sml | 72 ++++++++++++++++++++++++++++++++++++++- fcore/game-type.sml | 12 +++++-- fcore/game-update.sml | 48 ++++++++++++++------------ fcore/player.sml | 24 +++++++------ fcore/quad-tree.sml | 2 +- oms.mlb | 3 +- shell/gl-draw.sml | 6 +++- vendored/brolib-sml | 2 +- 8 files changed, 129 insertions(+), 40 deletions(-) diff --git a/fcore/enemy/enemy-map.sml b/fcore/enemy/enemy-map.sml index 02ccd97..540dbea 100644 --- a/fcore/enemy/enemy-map.sml +++ b/fcore/enemy/enemy-map.sml @@ -10,4 +10,74 @@ struct val maxNodeSize = 8 end -structure EnemyMap = MakeGapMap (EnemyPair) +structure EnemyMap = MakeGapMap(EnemyPair) + +structure EnemyTreeFolder = +struct + structure Pair = EnemyPair + + type env = unit + type state = QuadTree.t + + fun fold (enemyID, enemy: EnemyType.enemy, (), quadTree) = + let + val {id, x, y, ...} = enemy + val size = Constants.enemySize + in + QuadTree.insert (x, y, size, size, id, quadTree) + end +end + +structure MakeEnemyTree = MakeGapMapFolder(EnemyTreeFolder) + +structure EnemyDrawVec = + MakeGapMapFolder + (struct + structure Pair = EnemyPair + + type env = Real32.real * Real32.real + type state = Real32.real vector list + + fun helpGetDrawVec (enemy: EnemyType.enemy, width, height) = + let + val {x, y, ...} = enemy + val wratio = width / Constants.worldWidthReal + val hratio = height / Constants.worldHeightReal + in + if wratio < hratio then + let + val scale = Constants.worldHeightReal * wratio + val yOffset = + if height > scale then (height - scale) / 2.0 + else if height < scale then (scale - height) / 2.0 + else 0.0 + + val x = Real32.fromInt x * wratio + val y = Real32.fromInt y * wratio + yOffset + + val realSize = Constants.enemySizeReal * wratio + in + Block.lerp + (x, y, realSize, realSize, width, height, 0.5, 0.5, 1.0) + end + else + let + val scale = Constants.worldWidthReal * hratio + val xOffset = + if width > scale then (width - scale) / 2.0 + else if width < scale then (scale - width) / 2.0 + else 0.0 + + val x = Real32.fromInt x * hratio + xOffset + val y = Real32.fromInt y * hratio + + val realSize = Constants.enemySizeReal * hratio + in + Block.lerp + (x, y, realSize, realSize, width, height, 0.5, 0.5, 1.0) + end + end + + fun fold (_, enemy: EnemyType.enemy, (width, height), acc) = + helpGetDrawVec (enemy, width, height) :: acc + end) diff --git a/fcore/game-type.sml b/fcore/game-type.sml index 60de393..9dbf68e 100644 --- a/fcore/game-type.sml +++ b/fcore/game-type.sml @@ -41,7 +41,7 @@ sig , wallTree: QuadTree.t , platforms: platform vector , platformTree: QuadTree.t - , enemies: EnemyType.enemy vector + , enemies: EnemyMap.t , graph: PlatSet.elem vector vector , fallingEnemies: EnemyType.falling_enemy vector } @@ -93,11 +93,17 @@ struct , wallTree: QuadTree.t , platforms: platform vector , platformTree: QuadTree.t - , enemies: EnemyType.enemy vector + , enemies: EnemyMap.t , graph: PlatSet.elem vector vector , fallingEnemies: EnemyType.falling_enemy vector } + fun enemyMapFromList (hd :: tl, map) = + let val map = EnemyMap.add (#id hd, hd, map) + in enemyMapFromList (tl, map) + end + | enemyMapFromList ([], map) = map + val initial: game_type = let val player = @@ -175,7 +181,7 @@ struct , batMaxY = 485 , batMinY = 625 } - val enemies = Vector.fromList [enemy1] + val enemies = enemyMapFromList ([enemy1], EnemyMap.empty) val graph = Graph.fromPlatforms (platforms, platformTree) in { player = player diff --git a/fcore/game-update.sml b/fcore/game-update.sml index b001448..8caa804 100644 --- a/fcore/game-update.sml +++ b/fcore/game-update.sml @@ -13,32 +13,38 @@ struct , fallingEnemies } = game - val enemyTree = Enemy.generateTree enemies + val enemyTree = MakeEnemyTree.foldUnordered + ( enemies + , () + , QuadTree.create (Constants.worldWidth, Constants.worldHeight) + ) val player = Player.runPhysicsAndInput (game, input, enemyTree) val projectiles = #projectiles player val projectileTree = Projectile.generateTree projectiles - (* update state of falling enemies and possibly filter *) - val fallingEnemies = FallingEnemies.updateList - (Vector.length fallingEnemies - 1, fallingEnemies, player, []) - - val (enemies, fallingEnemies) = Enemy.updateEnemyList - ( Vector.length enemies - 1 - , enemies - , projectiles - , projectileTree - , walls - , wallTree - , platforms - , platformTree - , player - , graph - , [] - , fallingEnemies - ) - - val fallingEnemies = Vector.fromList fallingEnemies + (* update state of falling enemies and possibly filter *) + (* todo: use enemy map + val fallingEnemies = FallingEnemies.updateList + (Vector.length fallingEnemies - 1, fallingEnemies, player, []) + + val (enemies, fallingEnemies) = Enemy.updateEnemyList + ( Vector.length enemies - 1 + , enemies + , projectiles + , projectileTree + , walls + , wallTree + , platforms + , platformTree + , player + , graph + , [] + , fallingEnemies + ) + + val fallingEnemies = Vector.fromList fallingEnemies + *) in { player = player , walls = walls diff --git a/fcore/player.sml b/fcore/player.sml index 59fdb73..224199c 100644 --- a/fcore/player.sml +++ b/fcore/player.sml @@ -316,7 +316,7 @@ struct structure FoldEnemies = MakeQuadTreeFold (struct - type env = EnemyType.enemy vector * player + type env = EnemyMap.t * player type state = PlayerPatch.player_patch list fun getEnemyRecoilPatches (player, playerOnRight, acc) = @@ -349,14 +349,19 @@ struct val pFinishX = x + Constants.playerSize val pHalfW = Constants.playerSize div 2 val pCentreX = x + pHalfW - - val {x = ex, y = ey, ...} = Enemy.find (enemyID, enemies) - val eFinishX = ex + Constants.enemySize - val eHalfW = Constants.enemySize div 2 - val eCentreX = ex + eHalfW in - eCentreX < pCentreX + case EnemyMap.get (enemyID, enemies) of + SOME {x = ex, y = ey, ...} => + let + val eFinishX = ex + Constants.enemySize + val eHalfW = Constants.enemySize div 2 + val eCentreX = ex + eHalfW + in + eCentreX < pCentreX + end + | NONE => false end + val patches = getEnemyRecoilPatches (player, playerOnRight, patches) in @@ -437,10 +442,7 @@ struct end val patches = - (* if player is attacking, check if enemies collide with attack - * todo: MAIN_ATTACKING variant should hold an integer, - * and be compared with attackLengthLimit - * and the attack should shrink at some point as well *) + (* if player is attacking, check if enemies collide with attack *) case #mainAttack player of MAIN_ATTACKING {length, ...} => let diff --git a/fcore/quad-tree.sml b/fcore/quad-tree.sml index 611ae87..d62640c 100644 --- a/fcore/quad-tree.sml +++ b/fcore/quad-tree.sml @@ -1,6 +1,6 @@ signature QUAD_TREE = sig - type t + type t = {tree: QuadTreeType.t, width: int, height: int} val insert: int * int * int * int * int * t -> t diff --git a/oms.mlb b/oms.mlb index 94adff9..f283667 100644 --- a/oms.mlb +++ b/oms.mlb @@ -1,7 +1,6 @@ $(SML_LIB)/basis/basis.mlb (* fcore *) -vendored/brolib-sml/src/gap_map.sml fcore/constants.sml fcore/collision.sml @@ -9,6 +8,8 @@ fcore/quad-tree-type.sml fcore/quad-tree-fold.sml fcore/quad-tree.sml +vendored/brolib-sml/src/gap_map.sml + fcore/bin-search.sml fcore/bin-vec.sml diff --git a/shell/gl-draw.sml b/shell/gl-draw.sml index 8f632a7..c6bf685 100644 --- a/shell/gl-draw.sml +++ b/shell/gl-draw.sml @@ -236,7 +236,11 @@ struct val game = GameUpdate.update (game, input) val playerVec = Player.getDrawVec (#player game, width, height) - val enemyVec = Enemy.getDrawVec (#enemies game, width, height) + + val enemyVec = + EnemyDrawVec.foldUnordered (#enemies game, (width, height), []) + val enemyVec = Vector.concat enemyVec + val playerVec = Vector.concat [playerVec, enemyVec] val wallVec = Wall.getDrawVec (#walls game, width, height) diff --git a/vendored/brolib-sml b/vendored/brolib-sml index f3cc41e..5f834dd 160000 --- a/vendored/brolib-sml +++ b/vendored/brolib-sml @@ -1 +1 @@ -Subproject commit f3cc41e9a2d62c4f90eacd9557922427df939768 +Subproject commit 5f834ddaa4d5a10eb3e17f8f3c25cc7b992ad124