precompute graph to be used for dijkstra's algorithm, resulting in CPU usage that never exceed 7/home/humza/Downloads/sml/oh-my-stars/fcore/path-finding.sml with 5 enemies and eliminating lag
This commit is contained in:
@@ -1,244 +0,0 @@
|
|||||||
structure BuildGraph =
|
|
||||||
struct
|
|
||||||
fun insertIfNotExistsOrShorter (dist, eKeys, eVals, foldPlatID, q, fromPlatID) =
|
|
||||||
let
|
|
||||||
val pos = IntSet.findInsPos (foldPlatID, eKeys)
|
|
||||||
in
|
|
||||||
if pos <> ~1 andalso pos <> Vector.length eKeys then
|
|
||||||
let
|
|
||||||
val key = IntSet.sub (eKeys, pos)
|
|
||||||
in
|
|
||||||
if pos = key then
|
|
||||||
(* may need to update record in eVals if it is shorter *)
|
|
||||||
let
|
|
||||||
val {distance = oldDist, ...} = ValSet.sub (eVals, pos)
|
|
||||||
in
|
|
||||||
if dist < oldDist then
|
|
||||||
(* update values as we found a shorter path *)
|
|
||||||
let
|
|
||||||
val eVals =
|
|
||||||
ValSet.updateAtIdx
|
|
||||||
(eVals, {distance = dist, from = fromPlatID}, pos)
|
|
||||||
in
|
|
||||||
(eVals, q)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
(* return existing *)
|
|
||||||
(eVals, q)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
(* key not explored, so add to queue *)
|
|
||||||
let
|
|
||||||
val insRecord =
|
|
||||||
{distance = dist, id = foldPlatID, comesFrom = fromPlatID}
|
|
||||||
val insPos = DistVec.findInsPos (insRecord, q)
|
|
||||||
val q = DistVec.insert (q, insRecord, insPos)
|
|
||||||
in
|
|
||||||
(eVals, q)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
(* key not explored, so add to queue *)
|
|
||||||
let
|
|
||||||
val insRecord =
|
|
||||||
{distance = dist, id = foldPlatID, comesFrom = fromPlatID}
|
|
||||||
val insPos = DistVec.findInsPos (insRecord, q)
|
|
||||||
val q = DistVec.insert (q, insRecord, insPos)
|
|
||||||
in
|
|
||||||
(eVals, q)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
type env =
|
|
||||||
{ platforms: GameType.platform vector
|
|
||||||
, currentPlat: GameType.platform
|
|
||||||
, eKeys: IntSet.elem vector
|
|
||||||
, distSoFar: int
|
|
||||||
}
|
|
||||||
|
|
||||||
(* adds platforms to queue if they have not been explored
|
|
||||||
* or, if they have been explored and distance is smaller than previous,
|
|
||||||
* updates their distance.
|
|
||||||
* Only intended for platforms which can be reached vertically
|
|
||||||
* (jumped to or dropped to without moving left or right at the same time).
|
|
||||||
* *)
|
|
||||||
structure Vertical =
|
|
||||||
MakeQuadTreeFold
|
|
||||||
(struct
|
|
||||||
type env = env
|
|
||||||
|
|
||||||
type state = ValSet.elem vector * DistVec.elem vector
|
|
||||||
|
|
||||||
fun fold (foldPlatID, env: env, (eVals, q)) =
|
|
||||||
let
|
|
||||||
val {platforms, currentPlat, eKeys, distSoFar} = env
|
|
||||||
|
|
||||||
val {y = foldPlatY, ...} = Platform.find (foldPlatID, platforms)
|
|
||||||
val {y = currentPlatY, id = fromPlatID, ...} = currentPlat
|
|
||||||
val newDist = abs (foldPlatY - currentPlatY) + distSoFar
|
|
||||||
in
|
|
||||||
insertIfNotExistsOrShorter
|
|
||||||
(newDist, eKeys, eVals, foldPlatID, q, fromPlatID)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
(* trace paths for movements:
|
|
||||||
* jump + move right, or drop + move right,
|
|
||||||
* jump + move left, drop + move right *)
|
|
||||||
structure Horizontal =
|
|
||||||
MakeQuadTreeFold
|
|
||||||
(struct
|
|
||||||
type env = env
|
|
||||||
|
|
||||||
type state = ValSet.elem vector * DistVec.elem vector
|
|
||||||
|
|
||||||
fun minWidth (p1: GameType.platform, p2: GameType.platform) =
|
|
||||||
let
|
|
||||||
val {x = p1x, width = p1w, ...} = p1
|
|
||||||
val {x = p2x, width = p2w, ...} = p2
|
|
||||||
|
|
||||||
val p1fx = p1x + p1w
|
|
||||||
val p2fx = p2x + p2w
|
|
||||||
|
|
||||||
val w1 = abs (p1fx - p2fx)
|
|
||||||
val w2 = abs (p1fx - p2x)
|
|
||||||
val w3 = abs (p1x - p2x)
|
|
||||||
val w4 = abs (p1x - p2fx)
|
|
||||||
|
|
||||||
val min = Int.min (w1, w2)
|
|
||||||
val min = Int.min (min, w3)
|
|
||||||
in
|
|
||||||
Int.min (min, w4)
|
|
||||||
end
|
|
||||||
|
|
||||||
fun pythagoras (width, height) =
|
|
||||||
let
|
|
||||||
val wsq = width * width
|
|
||||||
val hsq = height * height
|
|
||||||
val hypotenuseSq = wsq + hsq
|
|
||||||
val hypSq = Real.fromInt hypotenuseSq
|
|
||||||
val hyp = Math.sqrt hypSq
|
|
||||||
in
|
|
||||||
Real.toInt IEEEReal.TO_NEAREST hyp
|
|
||||||
end
|
|
||||||
|
|
||||||
fun fold (foldPlatID, env: env, (eVals, q)) =
|
|
||||||
let
|
|
||||||
val {platforms, currentPlat, eKeys, distSoFar} = env
|
|
||||||
|
|
||||||
val foldPlat = Platform.find (foldPlatID, platforms)
|
|
||||||
val foldPlatY = #y foldPlat
|
|
||||||
val {y = currentPlatY, id = fromPlatID, ...} = currentPlat
|
|
||||||
|
|
||||||
val height = abs (foldPlatY - currentPlatY)
|
|
||||||
val width = minWidth (currentPlat, foldPlat)
|
|
||||||
|
|
||||||
val newDist = pythagoras (width, height) + distSoFar
|
|
||||||
in
|
|
||||||
insertIfNotExistsOrShorter
|
|
||||||
(newDist, eKeys, eVals, foldPlatID, q, fromPlatID)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
fun traceRightDescent (x, y, platTree, env, state) =
|
|
||||||
if x >= Constants.worldWidth orelse y >= Constants.worldHeight then
|
|
||||||
(* we hit bounds of screen and saw that there was
|
|
||||||
* no way to jump to next nextPlatID *)
|
|
||||||
state
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val width = Constants.moveEnemyBy
|
|
||||||
val height = Constants.worldHeight - y
|
|
||||||
val state = Horizontal.foldRegion
|
|
||||||
(x, y, width, height, env, state, platTree)
|
|
||||||
|
|
||||||
val nextX = x + Constants.moveEnemyBy
|
|
||||||
val nextY = y + Constants.moveEnemyBy
|
|
||||||
in
|
|
||||||
traceRightDescent (nextX, nextY, platTree, env, state)
|
|
||||||
end
|
|
||||||
|
|
||||||
fun traceRightJumpAscent (x, y, remainingJump, platTree, env, state) =
|
|
||||||
if remainingJump >= Constants.jumpLimit - Constants.enemySize then
|
|
||||||
traceRightDescent (x, y, platTree, env, state)
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val width = Constants.moveEnemyBy
|
|
||||||
val height = Constants.worldHeight - y
|
|
||||||
|
|
||||||
val state = Horizontal.foldRegion
|
|
||||||
(x, y, width, height, env, state, platTree)
|
|
||||||
|
|
||||||
val nextX = x + Constants.moveEnemyBy
|
|
||||||
val nextY = y - Constants.moveEnemyBy
|
|
||||||
val nextJump = remainingJump + Constants.moveEnemyBy
|
|
||||||
in
|
|
||||||
traceRightJumpAscent (nextX, nextY, nextJump, platTree, env, state)
|
|
||||||
end
|
|
||||||
|
|
||||||
fun traceRightJump (currentPlat: GameType.platform, env, state, platTree) =
|
|
||||||
let
|
|
||||||
val {x, y, width, ...} = currentPlat
|
|
||||||
val x = x - Constants.enemySize + width
|
|
||||||
in
|
|
||||||
traceRightJumpAscent (x, y, 0, platTree, env, state)
|
|
||||||
end
|
|
||||||
|
|
||||||
fun traceLeftDescent (x, y, platTree, env, state) =
|
|
||||||
if x <= 0 orelse y >= Constants.worldHeight then
|
|
||||||
state
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val width = Constants.moveEnemyBy
|
|
||||||
val height = Constants.worldHeight - y
|
|
||||||
val state = Horizontal.foldRegion
|
|
||||||
(x, y, width, height, env, state, platTree)
|
|
||||||
|
|
||||||
val nextX = x - Constants.moveEnemyBy
|
|
||||||
val nextY = y + Constants.moveEnemyBy
|
|
||||||
in
|
|
||||||
traceLeftDescent (nextX, nextY, platTree, env, state)
|
|
||||||
end
|
|
||||||
|
|
||||||
fun traceLeftJumpAscent (x, y, remainingJump, platTree, env, state) =
|
|
||||||
if remainingJump >= Constants.jumpLimit - Constants.enemySize then
|
|
||||||
traceLeftDescent (x, y, platTree, env, state)
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val width = Constants.moveEnemyBy
|
|
||||||
val height = Constants.worldHeight - y
|
|
||||||
|
|
||||||
val state = Horizontal.foldRegion
|
|
||||||
(x, y, width, height, env, state, platTree)
|
|
||||||
|
|
||||||
val nextX = x - Constants.moveEnemyBy
|
|
||||||
val nextY = y - Constants.moveEnemyBy
|
|
||||||
val nextJump = remainingJump + Constants.moveEnemyBy
|
|
||||||
in
|
|
||||||
traceLeftJumpAscent (nextX, nextY, nextJump, platTree, env, state)
|
|
||||||
end
|
|
||||||
|
|
||||||
fun traceLeftJump (currentPlat: GameType.platform, env, state, platTree) =
|
|
||||||
let
|
|
||||||
val {x, y, ...} = currentPlat
|
|
||||||
val x = x + Constants.enemySize
|
|
||||||
in
|
|
||||||
traceLeftJumpAscent (x, y, 0, platTree, env, state)
|
|
||||||
end
|
|
||||||
|
|
||||||
fun start (currentPlat: GameType.platform, env: env, state, platformTree) =
|
|
||||||
let
|
|
||||||
val {x, y, width, ...} = currentPlat
|
|
||||||
|
|
||||||
(* calculate area to search in y axis *)
|
|
||||||
val searchY = y - Constants.jumpLimit
|
|
||||||
val height = Constants.worldHeight - searchY
|
|
||||||
|
|
||||||
val state = Vertical.foldRegion
|
|
||||||
(x, searchY, width, height, env, state, platformTree)
|
|
||||||
|
|
||||||
val state = traceRightJump (currentPlat, env, state, platformTree)
|
|
||||||
in
|
|
||||||
traceLeftJump (currentPlat, env, state, platformTree)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -208,8 +208,7 @@ struct
|
|||||||
isBetween (platX, ecx, platFinishX)
|
isBetween (platX, ecx, platFinishX)
|
||||||
then
|
then
|
||||||
(* can jump from same position enemy is at *)
|
(* can jump from same position enemy is at *)
|
||||||
let
|
let in
|
||||||
in
|
|
||||||
case eyAxis of
|
case eyAxis of
|
||||||
ON_GROUND => EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM :: acc
|
ON_GROUND => EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM :: acc
|
||||||
| FALLING => EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM :: acc
|
| FALLING => EnemyPatch.W_Y_AXIS DROP_BELOW_PLATFORM :: acc
|
||||||
@@ -284,14 +283,12 @@ struct
|
|||||||
|
|
||||||
(* if only one side in x direction overlaps with platform,
|
(* if only one side in x direction overlaps with platform,
|
||||||
* then move enemy left/right to make them fully overlap with platform *)
|
* then move enemy left/right to make them fully overlap with platform *)
|
||||||
fun getHorizontalLandingPatches (enemy, nextPlatform, acc) =
|
fun getHorizontalLandingPatches (enemy, nextPlatform, acc) = acc
|
||||||
acc
|
|
||||||
|
|
||||||
fun getFallingPatches (enemy, newPlatformID, platforms, acc) =
|
fun getFallingPatches (enemy, newPlatformID, platforms, acc) =
|
||||||
EnemyPatch.W_NEXT_PLAT_ID ~1 :: acc
|
EnemyPatch.W_NEXT_PLAT_ID ~1 :: acc
|
||||||
|
|
||||||
fun getJumpLandingPatches (enemy, nextPlatformID, platforms, acc) =
|
fun getJumpLandingPatches (enemy, nextPlatformID, platforms, acc) = acc
|
||||||
acc
|
|
||||||
|
|
||||||
fun getLandingPatches (newPlatformID, platforms, enemy, acc) =
|
fun getLandingPatches (newPlatformID, platforms, enemy, acc) =
|
||||||
case #yAxis enemy of
|
case #yAxis enemy of
|
||||||
@@ -314,7 +311,7 @@ struct
|
|||||||
| _ => getPatrollPatches (enemy, wallTree, platformTree, acc)
|
| _ => getPatrollPatches (enemy, wallTree, platformTree, acc)
|
||||||
|
|
||||||
fun getFollowPatches
|
fun getFollowPatches
|
||||||
(player: player, enemy, wallTree, platformTree, platforms, acc) =
|
(player: player, enemy, wallTree, platformTree, platforms, graph, acc) =
|
||||||
let
|
let
|
||||||
val pID = #platID player
|
val pID = #platID player
|
||||||
val eID = #platID enemy
|
val eID = #platID enemy
|
||||||
@@ -331,7 +328,8 @@ struct
|
|||||||
startPatrolPatches (player, enemy, wallTree, platformTree, acc)
|
startPatrolPatches (player, enemy, wallTree, platformTree, acc)
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
val bestPath = PathFinding.start (pID, eID, platforms, platformTree)
|
val bestPath = PathFinding.start
|
||||||
|
(pID, eID, platforms, platformTree, graph)
|
||||||
in
|
in
|
||||||
case bestPath of
|
case bestPath of
|
||||||
nextPlatformID :: _ =>
|
nextPlatformID :: _ =>
|
||||||
@@ -355,7 +353,7 @@ struct
|
|||||||
end
|
end
|
||||||
|
|
||||||
fun getVariantPatches
|
fun getVariantPatches
|
||||||
(enemy, walls, wallTree, platforms, platformTree, player, acc) =
|
(enemy, walls, wallTree, platforms, platformTree, player, graph, acc) =
|
||||||
let
|
let
|
||||||
open EnemyVariants
|
open EnemyVariants
|
||||||
in
|
in
|
||||||
@@ -363,6 +361,6 @@ struct
|
|||||||
PATROL_SLIME => getPatrollPatches (enemy, wallTree, platformTree, acc)
|
PATROL_SLIME => getPatrollPatches (enemy, wallTree, platformTree, acc)
|
||||||
| FOLLOW_SIME =>
|
| FOLLOW_SIME =>
|
||||||
getFollowPatches
|
getFollowPatches
|
||||||
(player, enemy, wallTree, platformTree, platforms, acc)
|
(player, enemy, wallTree, platformTree, platforms, graph, acc)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
) =
|
) =
|
||||||
let
|
let
|
||||||
val {x, y, health, ...} = enemy
|
val {x, y, health, ...} = enemy
|
||||||
@@ -47,7 +48,15 @@ struct
|
|||||||
|
|
||||||
(* get patches specific to this type of enemy *)
|
(* get patches specific to this type of enemy *)
|
||||||
val patches = EnemyBehaviour.getVariantPatches
|
val patches = EnemyBehaviour.getVariantPatches
|
||||||
(enemy, walls, wallTree, platforms, platformTree, player, [])
|
( enemy
|
||||||
|
, walls
|
||||||
|
, wallTree
|
||||||
|
, platforms
|
||||||
|
, platformTree
|
||||||
|
, player
|
||||||
|
, graph
|
||||||
|
, []
|
||||||
|
)
|
||||||
val enemy = EnemyPatch.withPatches (enemy, patches)
|
val enemy = EnemyPatch.withPatches (enemy, patches)
|
||||||
|
|
||||||
val patches = EnemyPhysics.getPhysicsPatches enemy
|
val patches = EnemyPhysics.getPhysicsPatches enemy
|
||||||
@@ -66,7 +75,7 @@ struct
|
|||||||
|
|
||||||
(* get patches specific to this type of enemy *)
|
(* get patches specific to this type of enemy *)
|
||||||
val patches = EnemyBehaviour.getVariantPatches
|
val patches = EnemyBehaviour.getVariantPatches
|
||||||
(enemy, walls, wallTree, platforms, platformTree, player, [])
|
(enemy, walls, wallTree, platforms, platformTree, player, graph, [])
|
||||||
val enemy = EnemyPatch.withPatches (enemy, patches)
|
val enemy = EnemyPatch.withPatches (enemy, patches)
|
||||||
|
|
||||||
val patches = EnemyPhysics.getPhysicsPatches enemy
|
val patches = EnemyPhysics.getPhysicsPatches enemy
|
||||||
@@ -92,6 +101,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
) =
|
) =
|
||||||
if pos < 0 then
|
if pos < 0 then
|
||||||
Vector.fromList acc
|
Vector.fromList acc
|
||||||
@@ -107,6 +117,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
)
|
)
|
||||||
in
|
in
|
||||||
filterProjectileCollisions
|
filterProjectileCollisions
|
||||||
@@ -119,6 +130,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -136,6 +148,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
) =
|
) =
|
||||||
if pos < 0 then
|
if pos < 0 then
|
||||||
Vector.fromList acc
|
Vector.fromList acc
|
||||||
@@ -155,6 +168,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
)
|
)
|
||||||
in
|
in
|
||||||
filterWhenAttacked
|
filterWhenAttacked
|
||||||
@@ -168,6 +182,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ sig
|
|||||||
, platforms: platform vector
|
, platforms: platform vector
|
||||||
, platformTree: QuadTree.t
|
, platformTree: QuadTree.t
|
||||||
, enemies: enemy vector
|
, enemies: enemy vector
|
||||||
|
, graph: PlatSet.elem vector vector
|
||||||
}
|
}
|
||||||
|
|
||||||
val initial: game_type
|
val initial: game_type
|
||||||
@@ -140,6 +141,7 @@ struct
|
|||||||
, platforms: platform vector
|
, platforms: platform vector
|
||||||
, platformTree: QuadTree.t
|
, platformTree: QuadTree.t
|
||||||
, enemies: enemy vector
|
, enemies: enemy vector
|
||||||
|
, graph: PlatSet.elem vector vector
|
||||||
}
|
}
|
||||||
|
|
||||||
val initial: game_type =
|
val initial: game_type =
|
||||||
@@ -217,27 +219,49 @@ struct
|
|||||||
}
|
}
|
||||||
val enemy2 =
|
val enemy2 =
|
||||||
{ id = 2
|
{ id = 2
|
||||||
, x = 555
|
, x = 777
|
||||||
, y = 945
|
, y = 333
|
||||||
, health = 1
|
, health = 1
|
||||||
, xAxis = MOVE_LEFT
|
, xAxis = MOVE_LEFT
|
||||||
, yAxis = FALLING
|
, yAxis = FALLING
|
||||||
, variant = EnemyVariants.PATROL_SLIME
|
, variant = EnemyVariants.FOLLOW_SLIME
|
||||||
, platID = ~1
|
, platID = ~1
|
||||||
, nextPlatID = ~1
|
, nextPlatID = ~1
|
||||||
}
|
}
|
||||||
val enemy3 =
|
val enemy3 =
|
||||||
{ id = 3
|
{ id = 3
|
||||||
, x = 979
|
, x = 555
|
||||||
, y = 945
|
, y = 135
|
||||||
, health = 1
|
, health = 1
|
||||||
, xAxis = MOVE_RIGHT
|
, xAxis = MOVE_RIGHT
|
||||||
, yAxis = FALLING
|
, yAxis = FALLING
|
||||||
, variant = EnemyVariants.PATROL_SLIME
|
, variant = EnemyVariants.FOLLOW_SLIME
|
||||||
, platID = ~1
|
, platID = ~1
|
||||||
, nextPlatID = ~1
|
, nextPlatID = ~1
|
||||||
}
|
}
|
||||||
val enemies = Vector.fromList [enemy1]
|
val enemy4 =
|
||||||
|
{ id = 4
|
||||||
|
, x = 555
|
||||||
|
, y = 555
|
||||||
|
, health = 1
|
||||||
|
, xAxis = MOVE_RIGHT
|
||||||
|
, yAxis = FALLING
|
||||||
|
, variant = EnemyVariants.FOLLOW_SLIME
|
||||||
|
, platID = ~1
|
||||||
|
, nextPlatID = ~1
|
||||||
|
}
|
||||||
|
val enemy5 =
|
||||||
|
{ id = 5
|
||||||
|
, x = 199
|
||||||
|
, y = 333
|
||||||
|
, health = 1
|
||||||
|
, xAxis = MOVE_RIGHT
|
||||||
|
, yAxis = FALLING
|
||||||
|
, variant = EnemyVariants.FOLLOW_SLIME
|
||||||
|
, platID = ~1
|
||||||
|
, nextPlatID = ~1
|
||||||
|
}
|
||||||
|
val enemies = Vector.fromList [enemy1, enemy2, enemy3, enemy4, enemy5]
|
||||||
in
|
in
|
||||||
{ player = player
|
{ player = player
|
||||||
, walls = walls
|
, walls = walls
|
||||||
@@ -245,6 +269,7 @@ struct
|
|||||||
, platforms = platforms
|
, platforms = platforms
|
||||||
, platformTree = platformTree
|
, platformTree = platformTree
|
||||||
, enemies = enemies
|
, enemies = enemies
|
||||||
|
, graph = Graph.fromPlatforms (platforms, platformTree)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ structure GameUpdate =
|
|||||||
struct
|
struct
|
||||||
fun update (game, input) =
|
fun update (game, input) =
|
||||||
let
|
let
|
||||||
val {player, walls, wallTree, platforms, platformTree, enemies} = game
|
val {player, walls, wallTree, platforms, platformTree, enemies, graph} =
|
||||||
|
game
|
||||||
|
|
||||||
val player = Player.runPhysicsAndInput (game, input)
|
val player = Player.runPhysicsAndInput (game, input)
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ struct
|
|||||||
, wallTree
|
, wallTree
|
||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
|
, graph
|
||||||
)
|
)
|
||||||
in
|
in
|
||||||
{ player = player
|
{ player = player
|
||||||
@@ -26,6 +28,7 @@ struct
|
|||||||
, platforms = platforms
|
, platforms = platforms
|
||||||
, platformTree = platformTree
|
, platformTree = platformTree
|
||||||
, enemies = enemies
|
, enemies = enemies
|
||||||
|
, graph = graph
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,8 +22,11 @@ struct
|
|||||||
PlatSet.insert (platSet, insRecord, pos)
|
PlatSet.insert (platSet, insRecord, pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
type env =
|
(* duplicate of type alias declared in GameType.
|
||||||
{platforms: GameType.platform vector, currentPlat: GameType.platform}
|
* SML's structural type system is nice for allowing this. *)
|
||||||
|
type platform = {id: int, x: int, y: int, width: int}
|
||||||
|
|
||||||
|
type env = {platforms: platform vector, currentPlat: platform}
|
||||||
|
|
||||||
structure Vertical =
|
structure Vertical =
|
||||||
MakeQuadTreeFold
|
MakeQuadTreeFold
|
||||||
@@ -51,7 +54,7 @@ struct
|
|||||||
|
|
||||||
type state = PlatSet.elem vector
|
type state = PlatSet.elem vector
|
||||||
|
|
||||||
fun minWidth (p1: GameType.platform, p2: GameType.platform) =
|
fun minWidth (p1: platform, p2: platform) =
|
||||||
let
|
let
|
||||||
val {x = p1x, width = p1w, ...} = p1
|
val {x = p1x, width = p1w, ...} = p1
|
||||||
val {x = p2x, width = p2w, ...} = p2
|
val {x = p2x, width = p2w, ...} = p2
|
||||||
@@ -134,7 +137,7 @@ struct
|
|||||||
traceRightJumpAscent (nextX, nextY, nextJump, platTree, env, platSet)
|
traceRightJumpAscent (nextX, nextY, nextJump, platTree, env, platSet)
|
||||||
end
|
end
|
||||||
|
|
||||||
fun traceRightJump (currentPlat: GameType.platform, env, platSet, platTree) =
|
fun traceRightJump (currentPlat: platform, env, platSet, platTree) =
|
||||||
let
|
let
|
||||||
val {x, y, width, ...} = currentPlat
|
val {x, y, width, ...} = currentPlat
|
||||||
val x = x - Constants.enemySize + width
|
val x = x - Constants.enemySize + width
|
||||||
@@ -176,7 +179,7 @@ struct
|
|||||||
traceLeftJumpAscent (nextX, nextY, nextJump, platTree, env, platSet)
|
traceLeftJumpAscent (nextX, nextY, nextJump, platTree, env, platSet)
|
||||||
end
|
end
|
||||||
|
|
||||||
fun traceLeftJump (currentPlat: GameType.platform, env, platSet, platTree) =
|
fun traceLeftJump (currentPlat: platform, env, platSet, platTree) =
|
||||||
let
|
let
|
||||||
val {x, y, ...} = currentPlat
|
val {x, y, ...} = currentPlat
|
||||||
val x = x + Constants.enemySize
|
val x = x + Constants.enemySize
|
||||||
@@ -184,7 +187,7 @@ struct
|
|||||||
traceLeftJumpAscent (x, y, 0, platTree, env, platSet)
|
traceLeftJumpAscent (x, y, 0, platTree, env, platSet)
|
||||||
end
|
end
|
||||||
|
|
||||||
fun start (currentPlat: GameType.platform, env: env, platSet, platformTree) =
|
fun start (currentPlat: platform, env: env, platSet, platformTree) =
|
||||||
let
|
let
|
||||||
val {x, y, width, ...} = currentPlat
|
val {x, y, width, ...} = currentPlat
|
||||||
|
|
||||||
@@ -201,12 +204,10 @@ struct
|
|||||||
end
|
end
|
||||||
|
|
||||||
fun build (currentPlat, platforms, platformTree) =
|
fun build (currentPlat, platforms, platformTree) =
|
||||||
let
|
let val env = {currentPlat = currentPlat, platforms = platforms}
|
||||||
val env = {currentPlat = currentPlat, platforms = platforms}
|
in start (currentPlat, env, PlatSet.empty, platformTree)
|
||||||
in
|
|
||||||
start (currentPlat, env, PlatSet.empty, platformTree)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
fun fromPlatforms (platforms: GameType.platform vector, platformTree) =
|
fun fromPlatforms (platforms: platform vector, platformTree) =
|
||||||
Vector.map (fn plat => build (plat, platforms, platformTree)) platforms
|
Vector.map (fn plat => build (plat, platforms, platformTree)) platforms
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -96,55 +96,7 @@ struct
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
(* dead loop function: remove after adding graph to game type
|
fun start (pID, eID, platforms, platformTree, graph) =
|
||||||
* and moving to other loop *)
|
|
||||||
fun loop (pID, eID, platforms, platformTree, q, eKeys, eVals) =
|
|
||||||
if IntSet.contains (pID, eKeys) then
|
|
||||||
(* return path if we explored pid *)
|
|
||||||
getPathList (pID, eID, eKeys, eVals)
|
|
||||||
else
|
|
||||||
(* continue dijkstra's algorithm *)
|
|
||||||
let
|
|
||||||
(* filtering duplicates because we have no decrease-key operation *)
|
|
||||||
val q = filterMinDuplicates (q, eKeys)
|
|
||||||
in
|
|
||||||
if DistVec.isEmpty q then
|
|
||||||
(* return empty list to signify that there is no path *)
|
|
||||||
[]
|
|
||||||
else
|
|
||||||
(* find reachable values from min in quad tree *)
|
|
||||||
let
|
|
||||||
val {distance = distSoFar, id = minID, comesFrom} =
|
|
||||||
DistVec.findMin q
|
|
||||||
val plat = Platform.find (minID, platforms)
|
|
||||||
|
|
||||||
(* add explored *)
|
|
||||||
val insPos = IntSet.findInsPos (minID, eKeys)
|
|
||||||
val eKeys = IntSet.insert (eKeys, minID, insPos)
|
|
||||||
val eVals =
|
|
||||||
ValSet.insert
|
|
||||||
(eVals, {distance = distSoFar, from = comesFrom}, insPos)
|
|
||||||
|
|
||||||
(* on each loop, increment distSoFar by 15.
|
|
||||||
* Result: paths that require jumps to fewer platforms are
|
|
||||||
* incentivised a little bit. *)
|
|
||||||
val env =
|
|
||||||
{ platforms = platforms
|
|
||||||
, currentPlat = plat
|
|
||||||
, eKeys = eKeys
|
|
||||||
, distSoFar = distSoFar + 15
|
|
||||||
}
|
|
||||||
|
|
||||||
(* fold over quad tree, updating any distances
|
|
||||||
* we find the shortest path for *)
|
|
||||||
val (eVals, q) =
|
|
||||||
BuildGraph.start (plat, env, (eVals, q), platformTree)
|
|
||||||
in
|
|
||||||
loop (pID, eID, platforms, platformTree, q, eKeys, eVals)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
fun start (pID, eID, platforms, platformTree) =
|
|
||||||
let
|
let
|
||||||
(* initialise data structures: the priority queue and the explored map *)
|
(* initialise data structures: the priority queue and the explored map *)
|
||||||
val q = DistVec.fromList [{distance = 0, id = eID, comesFrom = eID}]
|
val q = DistVec.fromList [{distance = 0, id = eID, comesFrom = eID}]
|
||||||
@@ -163,6 +115,6 @@ struct
|
|||||||
* then we're done reconstructing the path and can return the path list.
|
* then we're done reconstructing the path and can return the path list.
|
||||||
* *)
|
* *)
|
||||||
in
|
in
|
||||||
loop (pID, eID, platforms, platformTree, q, eKeys, eVals)
|
loop (pID, eID, platforms, platformTree, q, eKeys, eVals, graph)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ struct
|
|||||||
, wallTree
|
, wallTree
|
||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
|
, graph
|
||||||
) =
|
) =
|
||||||
let
|
let
|
||||||
val {x, y, mainAttack, attacked, ...} = player
|
val {x, y, mainAttack, attacked, ...} = player
|
||||||
@@ -35,6 +36,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
)
|
)
|
||||||
|
|
||||||
(* add collided enemies to player record,
|
(* add collided enemies to player record,
|
||||||
@@ -64,6 +66,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
)
|
)
|
||||||
in
|
in
|
||||||
(player, enemies)
|
(player, enemies)
|
||||||
@@ -89,6 +92,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
)
|
)
|
||||||
in
|
in
|
||||||
(player, enemies)
|
(player, enemies)
|
||||||
@@ -109,6 +113,7 @@ struct
|
|||||||
, platforms
|
, platforms
|
||||||
, platformTree
|
, platformTree
|
||||||
, player
|
, player
|
||||||
|
, graph
|
||||||
)
|
)
|
||||||
in
|
in
|
||||||
(player, enemies)
|
(player, enemies)
|
||||||
|
|||||||
8
oms.mlb
8
oms.mlb
@@ -19,6 +19,10 @@ end
|
|||||||
|
|
||||||
fcore/wall.sml
|
fcore/wall.sml
|
||||||
fcore/platform.sml
|
fcore/platform.sml
|
||||||
|
|
||||||
|
fcore/graph.sml
|
||||||
|
fcore/path-finding.sml
|
||||||
|
|
||||||
fcore/enemy-variants.sml
|
fcore/enemy-variants.sml
|
||||||
fcore/game-type.sml
|
fcore/game-type.sml
|
||||||
|
|
||||||
@@ -26,10 +30,6 @@ fcore/player-patch.sml
|
|||||||
fcore/enemy-patch.sml
|
fcore/enemy-patch.sml
|
||||||
fcore/physics.sml
|
fcore/physics.sml
|
||||||
|
|
||||||
fcore/build-graph.sml
|
|
||||||
fcore/graph.sml
|
|
||||||
fcore/path-finding.sml
|
|
||||||
|
|
||||||
fcore/trace-jump.sml
|
fcore/trace-jump.sml
|
||||||
fcore/enemy-behaviour.sml
|
fcore/enemy-behaviour.sml
|
||||||
fcore/enemy.sml
|
fcore/enemy.sml
|
||||||
|
|||||||
Reference in New Issue
Block a user