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 enemySizeReal: Real32.real = 35.0
val moveEnemyBy = 3
val batRestLimit = 55
val moveBatX = 1
val moveBatY = 2
val moveProjectileBy = 11
end

View File

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

View File

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

View File

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

View File

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

View File

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