76 lines
2 KiB
GDScript
76 lines
2 KiB
GDScript
class_name Board
|
|
extends Node3D
|
|
|
|
var dims: Vector2i
|
|
|
|
func _ready():
|
|
for piece in pieces():
|
|
dims.x = max(dims.x, piece.lpos.x)
|
|
dims.y = max(dims.y, piece.lpos.y)
|
|
|
|
# for zooming out to see the whole puzzle
|
|
func top_left_aabb() -> AABB:
|
|
return AABB(position-Vector3(1,0,1), Vector3.ONE*0.1)
|
|
|
|
func bottom_right_aabb() -> AABB:
|
|
return AABB(position + Vector3(dims.x, 0, dims.y) + Vector3(1,0,2), Vector3.ONE*0.1)
|
|
|
|
func pieces() -> Array[Piece]:
|
|
var sorted: Array[Piece] = []
|
|
for child in get_children():
|
|
if child is Piece:
|
|
sorted.push_back(child)
|
|
# important for consistency.
|
|
# everything involving pieces is done top to bottom, then left to right
|
|
# expensive? yes. wasteful? definitely. worth it? i think so.
|
|
sorted.sort_custom(func(a, b): return a.lpos.y < b.lpos.y or a.lpos.x < b.lpos.x)
|
|
return sorted
|
|
|
|
func pieces_at(pos: Vector2i) -> Array[Piece]:
|
|
var out: Array[Piece] = []
|
|
for piece in pieces():
|
|
if piece.lpos == pos:
|
|
out.push_back(piece)
|
|
return out
|
|
|
|
func find_piece_at(pos: Vector2i, filter: Callable) -> Piece:
|
|
var at := pieces_at(pos)
|
|
var idx := at.find_custom(filter)
|
|
if idx < 0: return
|
|
return at[idx]
|
|
|
|
func any_at(pos: Vector2i, filter: Callable) -> bool:
|
|
return pieces_at(pos).any(filter)
|
|
|
|
func type_at(pos: Vector2i, type: Piece.Type) -> Piece:
|
|
return find_piece_at(pos, func(p): return p.type == type)
|
|
|
|
# TODO: ball collisions
|
|
func solid_at(pos: Vector2i) -> bool:
|
|
return any_at(pos, func(p): return p.type == Piece.Type.Wall or p.type == Piece.Type.Ball or p.type == Piece.Type.Player)
|
|
|
|
func passable_at(pos: Vector2i) -> bool:
|
|
return not solid_at(pos)
|
|
|
|
func remove_piece(piece: Piece):
|
|
remove_child(piece)
|
|
|
|
func add_piece(piece: Piece):
|
|
add_child(piece)
|
|
|
|
func add_pieces(piece: Array[Piece]):
|
|
for p in piece:
|
|
add_piece(p)
|
|
|
|
func do_step():
|
|
for piece in pieces():
|
|
piece.do_step(self)
|
|
|
|
func undo_step() -> Callable:
|
|
var undos: Array[Callable] = []
|
|
for piece in pieces():
|
|
undos.push_back(piece.undo_step())
|
|
return func():
|
|
for undo in undos:
|
|
undo.call()
|