diff --git a/source/GridMap.gd b/source/GridMap.gd index c77e4d0..aef97b6 100644 --- a/source/GridMap.gd +++ b/source/GridMap.gd @@ -19,31 +19,31 @@ func _ready(): exploding_lines[y].translation = Vector3(nb_collumns/2, y, 1) func clear(): - for position in get_used_cells(): - set_cell_item(position.x, position.y, position.z, EMPTY_CELL) + for used_cell in get_used_cells(): + set_cell_item(used_cell.x, used_cell.y, used_cell.z, EMPTY_CELL) -func is_free_cell(position): +func is_free_cell(cell): return ( - 0 <= position.x and position.x < nb_collumns - and position.y >= 0 - and get_cell_item(position.x, position.y, 0) == GridMap.INVALID_CELL_ITEM + 0 <= cell.x and cell.x < nb_collumns + and cell.y >= 0 + and get_cell_item(cell.x, cell.y, cell.z) == INVALID_CELL_ITEM ) -func possible_positions(initial_positions, movement): +func possible_positions(initial_translations, movement): var position - var test_positions = [] + var test_translations = [] for i in range(4): - position = initial_positions[i] + movement + position = initial_translations[i] + movement if is_free_cell(position): - test_positions.append(position) - if test_positions.size() == Tetromino.NB_MINOES: - return test_positions + test_translations.append(position) + if test_translations.size() == Tetromino.NB_MINOES: + return test_translations else: return [] func lock(piece): var minoes_over_grid = 0 - for position in piece.positions(): + for position in piece.get_translations(): if position.y >= nb_lines: minoes_over_grid += 1 set_cell_item(position.x, position.y, 0, MINO) diff --git a/source/Main.gd b/source/Main.gd index 597929c..315023f 100644 --- a/source/Main.gd +++ b/source/Main.gd @@ -30,9 +30,6 @@ var autoshift_action = "" var playing = false -signal piece_dropped(score) -signal piece_locked(lines, t_spin) - func _ready(): load_user_data() @@ -46,23 +43,22 @@ func load_user_data(): $Stats/VBC/HighScore.text = str($Stats.high_score) save_game.close() -func _on_Start_start(level): +func new_game(level): $GridMap.clear() + if current_piece: + remove_child(current_piece) if held_piece: remove_child(held_piece) held_piece = null - current_piece_held = false autoshift_action = "" next_piece = random_piece() - new_piece() $MidiPlayer.position = 0 $Start.visible = false $Stats.new_game(level) + new_piece() resume() func new_piece(): - if current_piece: - remove_child(current_piece) current_piece = next_piece current_piece.translation = $GridMap/Matrix/Position3D.translation current_piece.emit_trail(true) @@ -95,8 +91,7 @@ func _on_Stats_level_up(): func _unhandled_input(event): if event.is_action_pressed("pause"): if playing: - pause() - $controls_ui.visible = true + pause($controls_ui) elif $controls_ui.enable_resume: resume() if event.is_action_pressed("toggle_fullscreen"): @@ -123,11 +118,9 @@ func _unhandled_input(event): if event.is_action_pressed("hard_drop"): hard_drop() if event.is_action_pressed("rotate_clockwise"): - if rotate(Tetromino.CLOCKWISE): - $MidiPlayer.move() + rotate(Tetromino.CLOCKWISE) if event.is_action_pressed("rotate_counterclockwise"): - if rotate(Tetromino.COUNTERCLOCKWISE): - $MidiPlayer.move() + rotate(Tetromino.COUNTERCLOCKWISE) if event.is_action_pressed("hold"): hold() @@ -144,28 +137,27 @@ func process_autoshift(): if move(movements[autoshift_action]): $MidiPlayer.move() if autoshift_action == "soft_drop": - emit_signal("piece_dropped", 1) + $Stats.piece_dropped(1) func hard_drop(): var score = 0 while move(movements["soft_drop"]): score += 2 - emit_signal("piece_dropped", score) + $Stats.piece_dropped(score) + $MidiPlayer.move() + $LockDelay.stop() lock() func move(movement): - if current_piece.move(movement): + var moved = current_piece.move(movement) + if moved: $LockDelay.start() - return true - else: - return false + return moved func rotate(direction): if current_piece.rotate(direction): $LockDelay.start() - return true - else: - return false + $MidiPlayer.move() func _on_DropTimer_timeout(): move(movements["soft_drop"]) @@ -176,7 +168,11 @@ func _on_LockDelay_timeout(): func lock(): if $GridMap.lock(current_piece): - emit_signal("piece_locked", $GridMap.clear_lines(), current_piece.t_spin) + var lines_cleared = $GridMap.clear_lines() + $Stats.piece_locked(lines_cleared, current_piece.t_spin) + if lines_cleared or current_piece.t_spin: + $MidiPlayer.piece_locked(lines_cleared) + remove_child(current_piece) new_piece() else: game_over() @@ -210,10 +206,11 @@ func resume(): held_piece.visible = true next_piece.visible = true -func pause(hide=true): +func pause(gui=null): playing = false $Stats.time = OS.get_system_time_secs() - $Stats.time - if hide: + if gui: + gui.visible = true $Stats.visible = false $GridMap.visible = false current_piece.visible = false @@ -226,21 +223,20 @@ func pause(hide=true): $Stats/Clock.stop() func game_over(): - pause(false) + pause() current_piece.emit_trail(false) $FlashText.print("GAME\nOVER") $ReplayButton.visible = true func _on_ReplayButton_pressed(): - pause() + pause($Start) $ReplayButton.visible = false - $Start.visible = true func _notification(what): match what: MainLoop.NOTIFICATION_WM_FOCUS_OUT: if playing: - pause() + pause($controls_ui.visible) MainLoop.NOTIFICATION_WM_QUIT_REQUEST: save_user_data() get_tree().quit() diff --git a/source/Main.tscn b/source/Main.tscn index 30a9f24..4ad8ee3 100644 --- a/source/Main.tscn +++ b/source/Main.tscn @@ -335,7 +335,7 @@ __meta__ = { [node name="Matrix" type="MeshInstance" parent="GridMap" index="0"] -transform = Transform( 8.5, 0, 0, 0, 20, 0, 0, 0, 1, 4.5, 9.5, 0 ) +transform = Transform( 10, 0, 0, 0, 20, 0, 0, 0, 1, 4.5, 9.5, 0 ) layers = 1 material_override = null cast_shadow = 1 @@ -423,7 +423,7 @@ autostart = false [node name="AutoShiftTimer" type="Timer" parent="." index="7"] process_mode = 1 -wait_time = 0.04 +wait_time = 0.03 one_shot = false autostart = false @@ -545,12 +545,6 @@ flat = false align = 1 _sections_unfolded = [ "Margin", "custom_colors", "custom_fonts" ] -[connection signal="piece_dropped" from="." to="Stats" method="_on_Main_piece_dropped"] - -[connection signal="piece_locked" from="." to="Stats" method="_on_Main_piece_locked"] - -[connection signal="piece_locked" from="." to="MidiPlayer" method="_on_Main_piece_locked"] - [connection signal="timeout" from="DropTimer" to="." method="_on_DropTimer_timeout"] [connection signal="timeout" from="LockDelay" to="." method="_on_LockDelay_timeout"] @@ -567,7 +561,7 @@ _sections_unfolded = [ "Margin", "custom_colors", "custom_fonts" ] [connection signal="level_up" from="Stats" to="." method="_on_Stats_level_up"] -[connection signal="start" from="Start" to="." method="_on_Start_start"] +[connection signal="start" from="Start" to="." method="new_game"] [connection signal="pressed" from="ReplayButton" to="." method="_on_ReplayButton_pressed"] diff --git a/source/MidiPlayer.gd b/source/MidiPlayer.gd index 8a7937d..f164e19 100644 --- a/source/MidiPlayer.gd +++ b/source/MidiPlayer.gd @@ -38,18 +38,17 @@ func unmute_channels(channels): for note in muted_events[channel_id]: _process_track_event_note_on(channel_status[channel_id], muted_events[channel_id][note]) -func _on_Main_piece_locked(lines, t_spin): - if lines or t_spin: - if lines == Tetromino.NB_MINOES: - for channel in LINE_CLEAR_CHANNELS: - channel_status[channel].vomume = 127 - $LineCLearTimer.wait_time = 0.86 - else: - for channel in LINE_CLEAR_CHANNELS: - channel_status[channel].vomume = 100 - $LineCLearTimer.wait_time = 0.43 - unmute_channels(LINE_CLEAR_CHANNELS) - $LineCLearTimer.start() +func piece_locked(lines): + if lines == Tetromino.NB_MINOES: + for channel in LINE_CLEAR_CHANNELS: + channel_status[channel].vomume = 127 + $LineCLearTimer.wait_time = 0.86 + else: + for channel in LINE_CLEAR_CHANNELS: + channel_status[channel].vomume = 100 + $LineCLearTimer.wait_time = 0.43 + unmute_channels(LINE_CLEAR_CHANNELS) + $LineCLearTimer.start() func _on_LineCLearTimer_timeout(): mute_channels(LINE_CLEAR_CHANNELS) diff --git a/source/Stats.gd b/source/Stats.gd index 603ea2d..f6972bf 100644 --- a/source/Stats.gd +++ b/source/Stats.gd @@ -48,15 +48,15 @@ func show_time(): var hours = int(time_elapsed/3600) $VBC/Time.text = str(hours) + ":%02d"%minutes + ":%02d"%seconds -func _on_Main_piece_dropped(ds): +func piece_dropped(ds): score += ds $VBC/Score.text = str(score) -func _on_Main_piece_locked(lines, t_spin): +func piece_locked(lines, t_spin): var ds if lines or t_spin: var text = T_SPIN_NAMES[t_spin] - if text: + if lines and t_spin: text += " " text += LINES_CLEARED_NAMES[lines] emit_signal("flash_text", text) @@ -67,9 +67,9 @@ func _on_Main_piece_locked(lines, t_spin): emit_signal("flash_text", str(ds)) score += ds $VBC/Score.text = str(score) - if score > high_score: - high_score = score - $VBC/HighScore.text = str(high_score) + if score > high_score: + high_score = score + $VBC/HighScore.text = str(high_score) # Combos if lines: combos += 1 diff --git a/source/Stats.tscn b/source/Stats.tscn index 971e7d5..68fbe9f 100644 --- a/source/Stats.tscn +++ b/source/Stats.tscn @@ -3,7 +3,7 @@ [ext_resource path="res://Stats.gd" type="Script" id=1] [ext_resource path="res://fonts/Gamer.ttf" type="DynamicFontData" id=2] -[sub_resource type="DynamicFont" id=2] +[sub_resource type="DynamicFont" id=1] size = 20 use_mipmaps = false @@ -11,7 +11,7 @@ use_filter = false font_data = ExtResource( 2 ) _sections_unfolded = [ "Font", "Settings" ] -[node name="Stats" type="MarginContainer" index="0"] +[node name="Stats" type="MarginContainer"] anchor_left = 0.5 anchor_top = 0.5 @@ -70,7 +70,7 @@ mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 -custom_fonts/font = SubResource( 2 ) +custom_fonts/font = SubResource( 1 ) custom_colors/font_color = Color( 0.756214, 0.921978, 0.990234, 1 ) text = "Score:" percent_visible = 1.0 @@ -93,7 +93,7 @@ mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 -custom_fonts/font = SubResource( 2 ) +custom_fonts/font = SubResource( 1 ) custom_colors/font_color = Color( 0.756214, 0.921978, 0.990234, 1 ) text = "0" align = 2 @@ -117,7 +117,7 @@ mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 -custom_fonts/font = SubResource( 2 ) +custom_fonts/font = SubResource( 1 ) custom_colors/font_color = Color( 0.756214, 0.921978, 0.990234, 1 ) text = "High score:" percent_visible = 1.0 @@ -140,7 +140,7 @@ mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 -custom_fonts/font = SubResource( 2 ) +custom_fonts/font = SubResource( 1 ) custom_colors/font_color = Color( 0.756214, 0.921978, 0.990234, 1 ) text = "0" align = 2 @@ -164,7 +164,7 @@ mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 -custom_fonts/font = SubResource( 2 ) +custom_fonts/font = SubResource( 1 ) custom_colors/font_color = Color( 0.756214, 0.921978, 0.990234, 1 ) text = "Time" percent_visible = 1.0 @@ -186,7 +186,7 @@ mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 -custom_fonts/font = SubResource( 2 ) +custom_fonts/font = SubResource( 1 ) custom_colors/font_color = Color( 0.756214, 0.921978, 0.990234, 1 ) text = "0:00:00" align = 2 @@ -209,7 +209,7 @@ mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 -custom_fonts/font = SubResource( 2 ) +custom_fonts/font = SubResource( 1 ) custom_colors/font_color = Color( 0.756214, 0.921978, 0.990234, 1 ) text = "Level:" percent_visible = 1.0 @@ -231,7 +231,7 @@ mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 -custom_fonts/font = SubResource( 2 ) +custom_fonts/font = SubResource( 1 ) custom_colors/font_color = Color( 0.756214, 0.921978, 0.990234, 1 ) text = "0" align = 2 @@ -254,7 +254,7 @@ mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 -custom_fonts/font = SubResource( 2 ) +custom_fonts/font = SubResource( 1 ) custom_colors/font_color = Color( 0.756214, 0.921978, 0.990234, 1 ) text = "Goal:" percent_visible = 1.0 @@ -276,7 +276,7 @@ mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 -custom_fonts/font = SubResource( 2 ) +custom_fonts/font = SubResource( 1 ) custom_colors/font_color = Color( 0.756214, 0.921978, 0.990234, 1 ) text = "0" align = 2 diff --git a/source/Tetrominos/Tetromino.gd b/source/Tetrominos/Tetromino.gd index 948d6b3..2c7acf7 100644 --- a/source/Tetrominos/Tetromino.gd +++ b/source/Tetrominos/Tetromino.gd @@ -73,51 +73,48 @@ const SUPER_ROTATION_SYSTEM = [ } ] -var minoes +var minoes = [] var grid_map var orientation = 0 var t_spin = NO_T_SPIN func _ready(): randomize() - minoes = [$Mino0, $Mino1, $Mino2, $Mino3] + for i in range(NB_MINOES): + minoes.append(get_node("Mino"+str(i))) grid_map = get_parent().get_node("GridMap") -func positions(): - var p = [] - for mino in minoes: - p.append(to_global(mino.translation)) - return p - -func rotated_positions(direction): - var translations = [to_global(minoes[0].translation) ] - for i in range(1, 4): - var v = to_global(minoes[i].translation) - v -= to_global(minoes[0].translation) - v = Vector3(-1*direction*v.y, direction*v.x, 0) - v += to_global(minoes[0].translation) - translations.append(v) - return translations - -func apply_positions(positions): +func set_translations(translations): for i in range(NB_MINOES): - minoes[i].translation = to_local(positions[i]) + minoes[i].translation = to_local(translations[i]) + +func get_translations(): + var translations = [] + for mino in minoes: + translations.append(to_global(mino.translation)) + return translations func move(movement): - if grid_map.possible_positions(positions(), movement): + if grid_map.possible_positions(get_translations(), movement): translate(movement) return true - else: - return false + return false func rotate(direction): - var rotated_positions = rotated_positions(direction) + var t = get_translations() + var rotated_translations = [t[0]] + for i in range(1, NB_MINOES): + var v = t[i] + v -= t[0] + v = Vector3(-1*direction*v.y, direction*v.x, 0) + v += t[0] + rotated_translations.append(v) var movements = SUPER_ROTATION_SYSTEM[orientation][direction] for i in range(movements.size()): - if grid_map.possible_positions(rotated_positions, movements[i]): + if grid_map.possible_positions(rotated_translations, movements[i]): orientation -= direction orientation %= NB_MINOES - apply_positions(rotated_positions) + set_translations(rotated_translations) translate(movements[i]) return i+1 return 0