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()) 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 #print("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 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(): # Initalization here setup(10,20) score_label = get_node("../score") set_process_input(true)