]> Untitled Git - catris.git/blob - script/board.gd
Broken: doesn't rotate correctly on the right side
[catris.git] / script / board.gd
1 extends Control
2 class_name Board
3
4
5 signal added_piece
6 signal end_round
7
8
9 @export var block_size: int = 20
10 @export var piece_catalogue: Array[PackedScene] = []
11
12 var _grid_filled: Array[bool] = []
13 var _player_position: Vector2i = Vector2i.ZERO
14 var _player_piece: Piece = null
15 var _grid_final_y_row: int = 0
16 var _grid_final_x_row: int = 0
17
18 var num_pieces: int = 0
19 const start_pos: Vector2i = Vector2i(5, 2)
20
21 func _ready() -> void:
22         assert(piece_catalogue.size() >= 1, "Expected at least one piece in catalogue")
23         
24         # calculate grid
25         _grid_final_y_row = size.y / block_size
26         _grid_final_x_row = size.x / block_size
27         print("Grid is " + str(_grid_final_x_row) + " by " + str(_grid_final_y_row))
28         
29         for i in range(0, _grid_final_x_row):
30                 for j in range(0, _grid_final_y_row):
31                         _grid_filled.append(false)
32         
33         _on_turn_timer_timeout()
34
35
36 func _input(event: InputEvent) -> void:
37         if event.is_action_pressed("player_left"):
38                 _move(Vector2i(-1, 0))
39         elif event.is_action_pressed("player_right"):
40                 _move(Vector2i(1, 0))
41                 
42         if event.is_action_pressed("player_up"):
43                 if _player_piece:
44                         _player_piece.rotate_cells_left()
45                         
46                         # if player piece has cells off to the right or left of the board,
47                         # then shift it back onto the board
48                         var leftmost: int = 0
49                         var rightmost: int = 0
50                         for pos: Vector2i in _player_piece.get_cell_grid():
51                                 pos += _player_position # remember, pos is relative!
52                                 if pos.x < leftmost:
53                                         leftmost = pos.x
54                                 elif pos.x > _grid_final_x_row - 1 and pos.x > rightmost:
55                                         rightmost = pos.x - _grid_final_x_row - 1
56                         
57         
58                         print("l,r: %d, %d" % [leftmost, rightmost])
59                         
60                         if leftmost < 0:
61                                 _move(-Vector2i(leftmost, 0))
62                         elif rightmost > 0:
63                                 _move(-Vector2i(rightmost, 0))
64
65         if event.is_action_pressed("player_down"):
66                 # move piece to bottom 
67                 var b := true
68                 while b:
69                         b = _move(Vector2i(0, 1))
70
71
72 func _add_player_piece():
73         var scene: PackedScene = piece_catalogue.pick_random()
74         var piece: Piece = scene.instantiate()
75         piece.block_size = block_size
76         
77         # TODO: start piece at center of board
78         _player_position = start_pos
79         piece.position = _player_position * block_size
80         _player_piece = piece
81         
82         # add piece to scene tree and emit signal
83         add_child(piece)
84         num_pieces += 1
85         added_piece.emit()
86
87
88 # returns TRUE if piece can move more, FALSE if end state 
89 func _move(v: Vector2i) -> bool:
90         assert(_player_piece != null, "Player piece must not be null")
91         
92         var new_player_position: Vector2i = _player_position + v
93         
94         # for each cell in the block, offset it by new position and check for collision
95         for pos: Vector2i in _player_piece.get_cell_grid():
96                 pos += new_player_position
97                 if pos.x < 0 or pos.x >= _grid_final_x_row:
98                         # ignore input that moves beyond lateral boundaries
99                         return false
100                 
101                 if _is_grid_position_taken(pos):
102                         # if movement is vertical and blocked, then we're done
103                         if v.y != 0:
104                                 end_round.emit()
105                         return false
106                         
107         # update player position
108         _player_position = new_player_position
109         if _player_piece:
110                 _player_piece.position = _player_position * block_size
111
112         # if any cell's at the bottom of the grid, we're done
113         for pos: Vector2i in _player_piece.get_cell_grid():
114                 pos += _player_position
115                 if (pos.y >= _grid_final_y_row - 1):
116                         end_round.emit()
117                         return false
118         
119         return true
120
121
122 func _on_end_round():
123                 # disconnect player controls from current piece
124                 var piece: Piece = _player_piece
125                 _player_piece = null
126                 
127                 # fill in collision grid with piece cells
128                 for pos: Vector2i in piece.get_cell_grid():
129                         pos += _player_position
130                         _set_grid_position(pos, true)
131                 
132                 # now start a new round
133                 _on_turn_timer_timeout()
134
135
136 func _on_turn_timer_timeout() -> void:
137         if _player_piece == null:
138                 _add_player_piece()
139         else:
140                 _move(Vector2i(0, 1))
141         %turnTimer.start()
142
143
144 func _set_grid_position(v: Vector2i, b: bool):
145         _grid_filled[v.x + v.y * _grid_final_x_row] = b
146
147
148 func _is_grid_position_taken(v: Vector2i) -> bool:
149         return _grid_filled[v.x + v.y * _grid_final_x_row]