godot-puzzle/board.gd

70 lines
1.7 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)
# todo: Array[Piece]
func pieces() -> Array:
# todo: sort for consistency
return get_children()
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()