1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
class_name Tetris
extends AspectRatioContainer
const ROWS = 20
const COLUMNS = 10
export(PoolColorArray) var colors
var current_shape: TetrisPiece
var matrix := Logic.create_matrix(ROWS, COLUMNS)
var bg_squares := []
var squares := []
func get_square(at: Vector2) -> Control:
return squares[at.y * COLUMNS + at.x]
func init_squares():
var bg := create_grid_container("background")
add_child(bg)
var fg := create_grid_container("foreground")
add_child(fg)
for _i in range(ROWS * COLUMNS):
var bg_square := ReferenceRect.new()
bg_square.editor_only = false
bg_square.border_width = 1.5
bg_square.border_color = Color.ghostwhite
bg_square.name = "%d" % _i
expand_control(bg_square)
bg.add_child(bg_square)
var fg_square = ColorRect.new()
fg_square.color = Color.transparent
fg_square.name = "%d" % _i
expand_control(fg_square)
fg.add_child(fg_square)
squares.append(fg_square)
func create_grid_container(name: String) -> GridContainer:
var g := GridContainer.new()
g.columns = COLUMNS
g.name = name
g.add_constant_override("hseparation", 0)
g.add_constant_override("vseparation", 0)
g.set_anchors_and_margins_preset(PRESET_WIDE)
return g
func expand_control(c: Control) -> void:
c.size_flags_horizontal = SIZE_EXPAND_FILL
c.size_flags_vertical = SIZE_EXPAND_FILL
c.set_anchors_and_margins_preset(PRESET_WIDE)
func _ready() -> void:
set_process(false)
assert(len(colors) == Logic.shapes.size()) # 7
ratio = float(COLUMNS) / float(ROWS)
init_squares()
start()
func start() -> void:
set_process(true)
# warning-ignore-all:integer_division
current_shape = TetrisPiece.new(Vector2((COLUMNS / 2) - 2, 0))
tick()
func draw_board(mat: Array = matrix.duplicate(true), shape: TetrisPiece = current_shape) -> void:
shape.embed(mat)
for y in range(ROWS):
for x in range(COLUMNS):
get_square(Vector2(x, y)).color = colors[mat[y][x] - 1] if mat[y][x] > 0 else Color.transparent
func _process(_delta):
if Input.is_action_just_pressed("ui_left"):
current_shape.move(Vector2(-1, 0), matrix)
elif Input.is_action_just_pressed("ui_right"):
current_shape.move(Vector2(1, 0), matrix)
if Input.is_action_just_pressed("ui_up"):
current_shape.rotate(matrix, true)
if Input.is_action_just_pressed("ui_down"):
while current_shape.move(Vector2(0, 1), matrix):
continue
tick(false)
else:
draw_board()
func tick(create_timer := true):
if create_timer:
var t := get_tree().create_timer(.25)
t.connect("timeout", self, "tick")
if not current_shape.move(Vector2(0, 1), matrix): # invalid move: cant go down
current_shape.embed(matrix)
current_shape = TetrisPiece.new(Vector2(randi() % (COLUMNS - 4), 0))
Logic.clear_lines(matrix)
print(ascii(matrix))
draw_board()
#warning-ignore:shadowed_variable
func ascii(matrix):
var s = "+"
for _x in range(COLUMNS):
s += "-"
s += "+"
#warning-ignore:shadowed_variable
for y in range(ROWS):
s += "\n" + ("|" if y != ROWS - 1 else "+")
for x in range(COLUMNS):
if matrix[y][x] > 0:
s += "ﱢ"
else:
s += "-"
s += ("|" if y != ROWS - 1 else "+")
return s
|