extends Control # Simple Tetris-like demo, (c) 2012 Juan Linietsky # Implemented by using a regular Control and drawing on it during the _draw() callback. # The drawing surface is updated only when changes happen (by calling update()) # Member variables var score = 0 var score_label = null const MAX_SHAPES = 7 var block = preload("block.png") var block_colors = [ Color(1, 0.5, 0.5), Color(0.5, 1, 0.5), Color(0.5, 0.5, 1), Color(0.8, 0.4, 0.8), Color(0.8, 0.8, 0.4), Color(0.4, 0.8, 0.8), Color(0.7, 0.7, 0.7)] var block_shapes = [ [ Vector2(0, -1), Vector2(0, 0), Vector2(0, 1), Vector2(0, 2) ], # I [ Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(0, 1) ], # O [ Vector2(-1, 1), Vector2(0, 1), Vector2(0, 0), Vector2(1, 0) ], # S [ Vector2(1, 1), Vector2(0, 1), Vector2(0, 0), Vector2(-1, 0) ], # Z [ Vector2(-1, 1), Vector2(-1, 0), Vector2(0, 0), Vector2(1, 0) ], # L [ Vector2(1, 1), Vector2(1, 0), Vector2(0, 0), Vector2(-1, 0) ], # J [ Vector2(0, 1), Vector2(1, 0), Vector2(0, 0), Vector2(-1, 0) ]] # T var block_rotations = [ Matrix32(Vector2(1, 0), Vector2(0, 1), Vector2()), Matrix32(Vector2(0, 1), Vector2(-1, 0), Vector2()), Matrix32(Vector2(-1, 0), Vector2(0, -1), Vector2()), Matrix32(Vector2(0, -1), Vector2(1, 0), Vector2())] var width = 0 var height = 0 var cells = {} var piece_active = false var piece_shape = 0 var piece_pos = Vector2() var piece_rot = 0 func piece_cell_xform(p, er = 0): var r = (4 + er + piece_rot) % 4 return piece_pos + block_rotations[r].xform(p) func _draw(): var sb = get_stylebox("bg", "Tree") # Use line edit bg draw_style_box(sb, Rect2(Vector2(), get_size()).grow(3)) var bs = block.get_size() for y in range(height): for x in range(width): if (Vector2(x, y) in cells): draw_texture_rect(block, Rect2(Vector2(x, y)*bs, bs), false, block_colors[cells[Vector2(x, y)]]) if (piece_active): for c in block_shapes[piece_shape]: draw_texture_rect(block, Rect2(piece_cell_xform(c)*bs, bs), false, block_colors[piece_shape]) func piece_check_fit(ofs, er = 0): for c in block_shapes[piece_shape]: var pos = piece_cell_xform(c, er) + ofs if (pos.x < 0): return false if (pos.y < 0): return false if (pos.x >= width): return false if (pos.y >= height): return false if (pos in cells): return false return true func new_piece(): piece_shape = randi() % MAX_SHAPES piece_pos = Vector2(width/2, 0) piece_active = true piece_rot = 0 if (piece_shape == 0): piece_pos.y += 1 if (not piece_check_fit(Vector2())): # Game over game_over() update() func test_collapse_rows(): var accum_down = 0 for i in range(height): var y = height - i - 1 var collapse = true for x in range(width): if (Vector2(x, y) in cells): if (accum_down): cells[Vector2(x, y + accum_down)] = cells[Vector2(x, y)] else: collapse = false if (accum_down): cells.erase(Vector2(x, y + accum_down)) if (collapse): accum_down += 1 score += accum_down*100 score_label.set_text(str(score)) func game_over(): piece_active = false get_node("gameover").set_text("Game over!") update() func restart_pressed(): score = 0 score_label.set_text("0") cells.clear() get_node("gameover").set_text("") piece_active = true get_node("../restart").release_focus() update() func piece_move_down(): if (!piece_active): return if (piece_check_fit(Vector2(0, 1))): piece_pos.y += 1 update() else: for c in block_shapes[piece_shape]: var pos = piece_cell_xform(c) cells[pos] = piece_shape test_collapse_rows() new_piece() func piece_rotate(): var adv = 1 if (not piece_check_fit(Vector2(), 1)): return piece_rot = (piece_rot + adv) % 4 update() func _input(ie): if (not piece_active): return if (!ie.is_pressed()): return if (ie.is_action("move_left")): if (piece_check_fit(Vector2(-1, 0))): piece_pos.x -= 1 update() elif (ie.is_action("move_right")): if (piece_check_fit(Vector2(1, 0))): piece_pos.x += 1 update() elif (ie.is_action("move_down")): piece_move_down() elif (ie.is_action("rotate")): piece_rotate() func setup(w, h): width = w height = h set_size(Vector2(w, h)*block.get_size()) new_piece() get_node("timer").start() func _ready(): setup(10, 20) score_label = get_node("../score") set_process_input(true)