extends Control class_name Board signal added_piece signal end_round @export var block_size: int = 20 @export var piece_catalogue: Array[PackedScene] = [] var _grid_filled: Array[bool] = [] var _player_position: Vector2i = Vector2i.ZERO var _player_piece: Piece = null var _grid_final_y_row: int = 0 var _grid_final_x_row: int = 0 var num_pieces: int = 0 const start_pos: Vector2i = Vector2i(5, 2) func _ready() -> void: assert(piece_catalogue.size() >= 1, "Expected at least one piece in catalogue") # calculate grid _grid_final_y_row = size.y / block_size _grid_final_x_row = size.x / block_size print("Grid is " + str(_grid_final_x_row) + " by " + str(_grid_final_y_row)) for i in range(0, _grid_final_x_row): for j in range(0, _grid_final_y_row): _grid_filled.append(false) _on_turn_timer_timeout() func _input(event: InputEvent) -> void: if event.is_action_pressed("player_left"): _move(Vector2i(-1, 0)) elif event.is_action_pressed("player_right"): _move(Vector2i(1, 0)) if event.is_action_pressed("player_up"): if _player_piece: _player_piece.rotate_cells_left() # if player piece has cells off to the right or left of the board, # then shift it back onto the board var leftmost: int = 0 var rightmost: int = 0 for pos: Vector2i in _player_piece.get_cell_grid(): pos += _player_position # remember, pos is relative! if pos.x < leftmost: leftmost = pos.x elif pos.x > _grid_final_x_row - 1 and pos.x > rightmost: rightmost = pos.x - _grid_final_x_row - 1 print("l,r: %d, %d" % [leftmost, rightmost]) if leftmost < 0: _move(-Vector2i(leftmost, 0)) elif rightmost > 0: _move(-Vector2i(rightmost, 0)) if event.is_action_pressed("player_down"): # move piece to bottom var b := true while b: b = _move(Vector2i(0, 1)) func _add_player_piece(): var scene: PackedScene = piece_catalogue.pick_random() var piece: Piece = scene.instantiate() piece.block_size = block_size # TODO: start piece at center of board _player_position = start_pos piece.position = _player_position * block_size _player_piece = piece # add piece to scene tree and emit signal add_child(piece) num_pieces += 1 added_piece.emit() # returns TRUE if piece can move more, FALSE if end state func _move(v: Vector2i) -> bool: assert(_player_piece != null, "Player piece must not be null") var new_player_position: Vector2i = _player_position + v # for each cell in the block, offset it by new position and check for collision for pos: Vector2i in _player_piece.get_cell_grid(): pos += new_player_position if pos.x < 0 or pos.x >= _grid_final_x_row: # ignore input that moves beyond lateral boundaries return false if _is_grid_position_taken(pos): # if movement is vertical and blocked, then we're done if v.y != 0: end_round.emit() return false # update player position _player_position = new_player_position if _player_piece: _player_piece.position = _player_position * block_size # if any cell's at the bottom of the grid, we're done for pos: Vector2i in _player_piece.get_cell_grid(): pos += _player_position if (pos.y >= _grid_final_y_row - 1): end_round.emit() return false return true func _on_end_round(): # disconnect player controls from current piece var piece: Piece = _player_piece _player_piece = null # fill in collision grid with piece cells for pos: Vector2i in piece.get_cell_grid(): pos += _player_position _set_grid_position(pos, true) # now start a new round _on_turn_timer_timeout() func _on_turn_timer_timeout() -> void: if _player_piece == null: _add_player_piece() else: _move(Vector2i(0, 1)) %turnTimer.start() func _set_grid_position(v: Vector2i, b: bool): _grid_filled[v.x + v.y * _grid_final_x_row] = b func _is_grid_position_taken(v: Vector2i) -> bool: return _grid_filled[v.x + v.y * _grid_final_x_row]