add code so that bat also moves vertically (in addition to previous horizontal movement) when updating enemy state

This commit is contained in:
2025-02-12 00:25:55 +00:00
parent 1dc3116b77
commit 4c8b404c09
6 changed files with 161 additions and 120 deletions

View File

@@ -30,7 +30,10 @@ struct
val enemySize = 35 val enemySize = 35
val enemySizeReal: Real32.real = 35.0 val enemySizeReal: Real32.real = 35.0
val moveEnemyBy = 3 val moveEnemyBy = 3
val batRestLimit = 55 val batRestLimit = 55
val moveBatX = 1
val moveBatY = 2
val moveProjectileBy = 11 val moveProjectileBy = 11
end end

View File

@@ -502,50 +502,58 @@ struct
fun updateStraightBat fun updateStraightBat
(player, enemy, walls, wallTree, projectileTree, enemyList, fallingList) = (player, enemy, walls, wallTree, projectileTree, enemyList, fallingList) =
let let
val {x, y, batRest, ...} = enemy val {x, y, batRest, batDirY, batMinY, batMaxY, xAxis, ...} = enemy
val size = Constants.enemySize val size = Constants.enemySize
in val moveByY = Constants.moveBatY
if QuadTree.hasCollisionAt (x, y, size, size, ~1, wallTree) then val moveByX = Constants.moveBatX
(* has collision with wall *)
let val patches =
val enemy = (* get apatches for up/down movement *)
if batRest >= Constants.batRestLimit then case batDirY of
(* make enemy move in opposite direction *) UP =>
case #xAxis enemy of if y - moveByY <= batMaxY then
MOVE_RIGHT => [EnemyPatch.W_BAT_DIR_Y DOWN, EnemyPatch.W_Y (y + moveByY)]
EnemyPatch.withPatches
( enemy
, [ EnemyPatch.W_X_AXIS MOVE_LEFT
, EnemyPatch.W_X (x - (Constants.moveEnemyBy * 9))
]
)
| MOVE_LEFT =>
EnemyPatch.withPatches
( enemy
, [ EnemyPatch.W_X_AXIS MOVE_RIGHT
, EnemyPatch.W_X (x + (Constants.moveEnemyBy * 9))
]
)
| _ => enemy
else else
(* keep resting until we hit rest limit *) [EnemyPatch.W_Y (y - moveByY)]
EnemyPatch.withPatch (enemy, EnemyPatch.W_BAT_REST (batRest + 1)) | DOWN =>
in if y + moveByY >= batMinY then
(enemy :: enemyList, fallingList) [EnemyPatch.W_BAT_DIR_Y UP, EnemyPatch.W_Y (y - moveByY)]
end else
else [EnemyPatch.W_Y (y + moveByY)]
(* no collision, so continue moving in direction *)
let val patches =
val patches = (* get patches for horizontal movement *)
case #xAxis enemy of if QuadTree.hasCollisionAt (x, y, size, size, ~1, wallTree) then
MOVE_RIGHT => [EnemyPatch.W_X (x + Constants.moveEnemyBy)] (* has collision with wall *)
| MOVE_LEFT => [EnemyPatch.W_X (x - Constants.moveEnemyBy)] if batRest >= Constants.batRestLimit then
| STAY_STILL => [] (* make enemy move in opposite direction *)
val patches = EnemyPatch.W_BAT_REST 0 :: patches case xAxis of
val enemy = EnemyPatch.withPatches (enemy, patches) MOVE_RIGHT =>
in EnemyPatch.W_X_AXIS MOVE_LEFT :: EnemyPatch.W_X (x - 1)
(enemy :: enemyList, fallingList) :: patches
end | MOVE_LEFT =>
EnemyPatch.W_X_AXIS MOVE_RIGHT :: EnemyPatch.W_X (x + 1)
:: patches
| _ => patches
else
(* keep resting until we hit rest limit *)
EnemyPatch.W_BAT_REST (batRest + 1) :: patches
else
(* no collision, so continue moving in direction *)
let
val patches =
case xAxis of
MOVE_RIGHT => EnemyPatch.W_X (x + moveByX) :: patches
| MOVE_LEFT => EnemyPatch.W_X (x - moveByX) :: patches
| STAY_STILL => patches
in
EnemyPatch.W_BAT_REST 0 :: patches
end
val enemy = EnemyPatch.withPatches (enemy, patches)
in
(enemy :: enemyList, fallingList)
end end
fun updateEnemyState fun updateEnemyState

View File

@@ -234,8 +234,8 @@ struct
, nextPlatID = ~1 , nextPlatID = ~1
, batRest = 0 , batRest = 0
, batDirY = UP , batDirY = UP
, batMaxY = 635 , batMaxY = 485
, batMinY = 475 , batMinY = 625
} }
val enemies = Vector.fromList [enemy1] val enemies = Vector.fromList [enemy1]
val graph = Graph.fromPlatforms (platforms, platformTree) val graph = Graph.fromPlatforms (platforms, platformTree)

View File

@@ -10,9 +10,15 @@ signature MAKE_QUAD_TREE_FOLD =
sig sig
structure Fn: QUAD_FOLDER structure Fn: QUAD_FOLDER
val foldRegion: int * int * int * int * val foldRegion:
Fn.env * Fn.state * {tree: QuadTreeType.t, width: int, height: int} int
-> Fn.state * int
* int
* int
* Fn.env
* Fn.state
* {tree: QuadTreeType.t, width: int, height: int}
-> Fn.state
end end
functor MakeQuadTreeFold(Fn: QUAD_FOLDER): MAKE_QUAD_TREE_FOLD = functor MakeQuadTreeFold(Fn: QUAD_FOLDER): MAKE_QUAD_TREE_FOLD =
@@ -50,38 +56,79 @@ struct
val state = val state =
if vtl then if vtl then
helpFoldRegion helpFoldRegion
(rx, ry, rw, rh, env, state, qx, qy, hw, hh, Vector.sub (nodes, tlIdx)) ( rx
, ry
, rw
, rh
, env
, state
, qx
, qy
, hw
, hh
, Vector.sub (nodes, tlIdx)
)
else else
state state
val state = val state =
if vtr then if vtr then
helpFoldRegion helpFoldRegion
(rx, ry, rw, rh, env, state, qx + hw, qy, hw, hh, Vector.sub (nodes, trIdx)) ( rx
else , ry
, rw
, rh
, env
, state
, qx + hw
, qy
, hw
, hh
, Vector.sub (nodes, trIdx)
)
else
state state
val state = val state =
if vbl then if vbl then
helpFoldRegion helpFoldRegion
(rx, ry, rw, rh, env, state, qx, qy + hh, hw, hh, Vector.sub (nodes, blIdx)) ( rx
, ry
, rw
, rh
, env
, state
, qx
, qy + hh
, hw
, hh
, Vector.sub (nodes, blIdx)
)
else else
state state
in in
if vbr then if vbr then
helpFoldRegion helpFoldRegion
(rx, ry, rw, rh, env, state, qw + hw, qy + hh, hw, hh, Vector.sub (nodes, brIdx)) ( rx
, ry
, rw
, rh
, env
, state
, qw + hw
, qy + hh
, hw
, hh
, Vector.sub (nodes, brIdx)
)
else else
state state
end end
| LEAF items => | LEAF items => foldRegionVec (rx, ry, rw, rh, env, state, 0, items)
foldRegionVec (rx, ry, rw, rh, env, state, 0, items)
fun foldRegion (rx, ry, rw, rh, env, state, tree) = fun foldRegion (rx, ry, rw, rh, env, state, tree) =
let let val {width, height, tree} = tree
val {width, height, tree} = tree in helpFoldRegion (rx, ry, rw, rh, env, state, 0, 0, width, height, tree)
in
helpFoldRegion (rx, ry, rw, rh, env, state, 0, 0, width, height, tree)
end end
end end

View File

@@ -2,51 +2,33 @@ signature QUAD_TREE_TYPE =
sig sig
type item = {itemID: int, startX: int, startY: int, width: int, height: int} type item = {itemID: int, startX: int, startY: int, width: int, height: int}
datatype t = datatype t = NODE of t vector | LEAF of item vector
NODE of t vector
| LEAF of item vector
val tlIdx: int val tlIdx: int
val trIdx: int val trIdx: int
val blIdx: int val blIdx: int
val brIdx: int val brIdx: int
val isColliding: int * int * int * int * val isColliding: int * int * int * int * int * int * int * int -> bool
int * int * int * int
-> bool
val isCollidingPlus: int * int * int * int * val isCollidingPlus: int * int * int * int * int * int * int * int -> bool
int * int * int * int
-> bool
val isCollidingItem: int * int * int * int * val isCollidingItem: int * int * int * int * int * item -> bool
int * item
-> bool
val visitTopLeft: int * int * int * int * val visitTopLeft: int * int * int * int * int * int * int * int -> bool
int * int * int * int
-> bool
val visitTopRight: int * int * int * int * val visitTopRight: int * int * int * int * int * int * int * int -> bool
int * int * int * int
-> bool
val visitBottomLeft: int * int * int * int * val visitBottomLeft: int * int * int * int * int * int * int * int -> bool
int * int * int * int
-> bool
val visitBottomRight: int * int * int * int * val visitBottomRight: int * int * int * int * int * int * int * int -> bool
int * int * int * int
-> bool
end end
structure QuadTreeType :> QUAD_TREE_TYPE = structure QuadTreeType :> QUAD_TREE_TYPE =
struct struct
type item = {itemID: int, startX: int, startY: int, width: int, height: int} type item = {itemID: int, startX: int, startY: int, width: int, height: int}
datatype t = datatype t = NODE of t vector | LEAF of item vector
NODE of t vector
| LEAF of item vector
val tlIdx = 0 val tlIdx = 0
val trIdx = 1 val trIdx = 1

View File

@@ -26,7 +26,7 @@ struct
val vec = Vector.fromList [] val vec = Vector.fromList []
val tree = LEAF vec val tree = LEAF vec
in in
{ tree = tree, width = width, height = height } {tree = tree, width = width, height = height}
end end
fun mkItem (id, startX, startY, width, height) : item = fun mkItem (id, startX, startY, width, height) : item =
@@ -41,10 +41,8 @@ struct
val maxSize = 16 val maxSize = 16
fun mkLeaf items = fun mkLeaf items =
let let val items = Vector.fromList items
val items = Vector.fromList items in LEAF items
in
LEAF items
end end
fun splitLeaf fun splitLeaf
@@ -65,7 +63,7 @@ struct
val tr = mkLeaf tr val tr = mkLeaf tr
val bl = mkLeaf bl val bl = mkLeaf bl
val br = mkLeaf br val br = mkLeaf br
val nodes = Vector.fromList [tl, tr, bl, br] val nodes = Vector.fromList [tl, tr, bl, br]
in in
NODE nodes NODE nodes
end end
@@ -101,20 +99,18 @@ struct
val tl = Vector.sub (nodes, tlIdx) val tl = Vector.sub (nodes, tlIdx)
val tl = val tl =
if vtl then if vtl then helpInsert (ix, iy, iw, ih, itemID, qw, qy, hw, hh, tl)
helpInsert (ix, iy, iw, ih, itemID, qw, qy, hw, hh, tl) else tl
else
tl
val tr = Vector.sub (nodes, trIdx) val tr = Vector.sub (nodes, trIdx)
val tr = val tr =
if vtr then if vtr then
helpInsert (ix, iy, iw, ih, itemID, qx + hw, qy, hw, hh, tr) helpInsert (ix, iy, iw, ih, itemID, qx + hw, qy, hw, hh, tr)
else else
tr tr
val bl = Vector.sub (nodes, blIdx) val bl = Vector.sub (nodes, blIdx)
val bl = val bl =
if vbl then if vbl then
helpInsert (ix, iy, iw, ih, itemID, qx, qy + hh, hw, hh, bl) helpInsert (ix, iy, iw, ih, itemID, qx, qy + hh, hw, hh, bl)
else else
@@ -124,7 +120,7 @@ struct
val br = val br =
if vbr then if vbr then
helpInsert (ix, iy, iw, ih, itemID, qx + hw, qy + hh, hw, hh, br) helpInsert (ix, iy, iw, ih, itemID, qx + hw, qy + hh, hw, hh, br)
else else
br br
val nodes = Vector.fromList [tl, tr, bl, br] val nodes = Vector.fromList [tl, tr, bl, br]
@@ -160,35 +156,40 @@ struct
fun insert (iX, iY, iW, iH, itemID, tree: t) = fun insert (iX, iY, iW, iH, itemID, tree: t) =
let let
val {width, height, tree} = tree val {width, height, tree} = tree
val tree = val tree = helpInsert (iX, iY, iW, iH, itemID, 0, 0, width, height, tree)
helpInsert (iX, iY, iW, iH, itemID, 0, 0, width, height, tree)
in in
{width = width, height = height, tree = tree} {width = width, height = height, tree = tree}
end end
structure GetCollisions = MakeQuadTreeFold (struct structure GetCollisions =
type env = unit MakeQuadTreeFold
type state = int list (struct
fun fold (itemID, (), lst) = itemID :: lst type env = unit
end) type state = int list
fun fold (itemID, (), lst) = itemID :: lst
end)
fun getCollisions (itemX, itemY, itemWidth, itemHeight, _, tree) = fun getCollisions (itemX, itemY, itemWidth, itemHeight, _, tree) =
GetCollisions.foldRegion (itemX, itemY, itemWidth, itemHeight, (), [], tree) GetCollisions.foldRegion (itemX, itemY, itemWidth, itemHeight, (), [], tree)
structure HasCollisionAt = MakeQuadTreeFold (struct structure HasCollisionAt =
type env = unit MakeQuadTreeFold
type state = bool (struct
fun fold _ = true type env = unit
end) type state = bool
fun fold _ = true
end)
fun hasCollisionAt (ix, iy, iw, ih, _, tree) = fun hasCollisionAt (ix, iy, iw, ih, _, tree) =
HasCollisionAt.foldRegion (ix, iy, iw, ih, (), false, tree) HasCollisionAt.foldRegion (ix, iy, iw, ih, (), false, tree)
structure GetItemID = MakeQuadTreeFold (struct structure GetItemID =
type env = unit MakeQuadTreeFold
type state = int (struct
fun fold (itemID, (), curID) = Int.max (itemID, curID) type env = unit
end) type state = int
fun fold (itemID, (), curID) = Int.max (itemID, curID)
end)
fun getItemID (ix, iy, iw, ih, tree) = fun getItemID (ix, iy, iw, ih, tree) =
GetItemID.foldRegion (ix, iy, iw, ih, (), ~1, tree) GetItemID.foldRegion (ix, iy, iw, ih, (), ~1, tree)