2025-04-23 15:37:03 +02:00
[gd_scene load_steps=7 format=3 uid="uid://ccgnnif026wb4"]
2025-04-20 23:25:51 +02:00
2025-04-21 16:06:56 +02:00
[ext_resource type="PackedScene" uid="uid://xd3nsiglcdfc" path="res://gui/timer.tscn" id="1_356j3"]
[ext_resource type="PackedScene" uid="uid://cckeamgkt8bqo" path="res://gui/speed.tscn" id="2_2gn6w"]
2025-04-23 15:37:03 +02:00
[ext_resource type="PackedScene" uid="uid://cn55m5dqo3m6u" path="res://gui/rings.tscn" id="3_mbj17"]
[ext_resource type="PackedScene" uid="uid://dkxtwpcy4moyo" path="res://menus/pause_menu.tscn" id="4_3bfj3"]
2025-02-23 00:46:23 +01:00
[sub_resource type="GDScript" id="GDScript_8n212"]
script/source = "extends Node
2025-03-25 17:48:00 +01:00
var playing: bool = false
2025-02-23 16:18:14 +01:00
var changing_level: bool = false
2025-03-25 17:48:00 +01:00
var current_level_int: int = 0
var levels = [
preload(\"res://levels/base/level.tscn\"),
preload(\"res://levels/forest/level.tscn\"),
preload(\"res://levels/night/level.tscn\"),
]
2025-03-30 15:40:22 +02:00
var area_resource = preload(\"res://menus/main/area.tscn\")
2025-02-23 00:46:23 +01:00
2025-04-23 15:37:03 +02:00
@onready var gui_timer := $GUI/TopLeft/Timer
@onready var gui_speed := $GUI/TopRight/Speed
@onready var gui_rings := $GUI/BottomRight/Rings
@onready var pause_menu := $PauseMenu
2025-04-20 23:25:51 +02:00
2025-02-23 16:18:14 +01:00
func _ready() -> void:
## Add the version of the game and the name of the OS to the footer of the start menu
2025-03-25 13:39:03 +01:00
if OS.has_feature(\"editor\"):
2025-03-30 15:40:22 +02:00
$DevInfos.text = \"dev \"
2025-04-23 15:37:03 +02:00
$DevInfos.text += \"build \" + ProjectSettings.get_setting(\"application/config/version\") + \" (\" + OS.get_name() + \")\"
## Hide UI stuff that shouldn't be visible until later in the game
$VictoryScreen.hide()
$GUI.hide()
pause_menu.hide()
## Connect to necessary signals
pause_menu.connect(\"request_pause\", pause_game)
pause_menu.connect(\"request_fullscreen\", fullscreen_game)
pause_menu.connect(\"request_restart\", restart_level)
2025-03-30 15:40:22 +02:00
launch_area()
func launch_area():
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
var area := area_resource.instantiate()
area.connect(\"request_start\", start_game)
$Levels.add_child(area)
2025-02-23 16:18:14 +01:00
2025-03-25 17:48:00 +01:00
## Get all the levels that are currently being played!
## In theory, there should ever be only zero or one,
## but it turns out it's more simple to handle things by using Arrays.
func get_current_levels() -> Array[Level]:
2025-03-30 15:40:22 +02:00
var children := $Levels.get_children(true)
2025-03-25 17:48:00 +01:00
var current_levels: Array[Level] = []
for child in children:
if is_instance_of(child, Level):
current_levels.push_back(child)
return current_levels
2025-02-23 00:46:23 +01:00
func start_level(level_scene: PackedScene) -> void:
2025-02-23 17:21:13 +01:00
$VictoryScreen.hide()
2025-03-25 17:48:00 +01:00
var level = level_scene.instantiate()
$Levels.add_child(level)
2025-03-25 23:18:33 +01:00
level.connect(\"completed\", stop_level)
2025-04-23 15:37:03 +02:00
level.connect(\"ring_collected\", func():
gui_rings.remaining_rings = len(level.rings) - level.finished_rings_count
)
gui_rings.remaining_rings = len(level.rings) - level.finished_rings_count
2025-03-25 17:48:00 +01:00
playing = true
PhysicsServer3D.area_set_param(
get_viewport().find_world_3d().space,
PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR,
Vector3.DOWN
)
changing_level = false
2025-04-23 15:37:03 +02:00
gui_timer.seconds_spent_level_attempt = 0.0
gui_timer.enabled = true
2025-02-23 00:46:23 +01:00
func stop_level() -> void:
2025-04-23 15:37:03 +02:00
gui_timer.enabled = false
2025-02-23 14:27:35 +01:00
PhysicsServer3D.area_set_param(get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY, 1)
2025-03-25 17:48:00 +01:00
playing = false
2025-02-23 16:18:14 +01:00
changing_level = true
2025-04-21 16:06:56 +02:00
2025-04-23 15:37:03 +02:00
SaveFiles.change_property(\"played_for\", gui_timer.seconds_spent_total, SaveFiles.selected_file)
2025-04-21 16:06:56 +02:00
var save_file_data = SaveFiles.read(SaveFiles.selected_file)
var property_name := \"best_time_for_level_\" + str(current_level_int)
2025-04-23 15:37:03 +02:00
if !save_file_data.has(property_name) or save_file_data[property_name] is not float or save_file_data[property_name] > gui_timer.seconds_spent_level_attempt:
SaveFiles.change_property(property_name, gui_timer.seconds_spent_level_attempt, SaveFiles.selected_file)
2025-02-23 00:46:23 +01:00
2025-03-25 17:48:00 +01:00
var current_levels = get_current_levels()
for level in current_levels:
level.music.fadeOut(2)
2025-03-24 18:13:08 +01:00
await get_tree().create_timer(2).timeout
2025-03-25 17:48:00 +01:00
level.queue_free()
2025-02-23 00:46:23 +01:00
2025-03-25 17:48:00 +01:00
if len(levels) > current_level_int + 1:
current_level_int += 1
start_level(levels[current_level_int])
else:
win_game()
func win_game() -> void:
$VictoryScreen.show()
await get_tree().create_timer(2).timeout
2025-03-30 15:40:22 +02:00
launch_area()
$VictoryScreen.hide()
2025-02-23 00:46:23 +01:00
2025-02-23 16:18:14 +01:00
func restart_level() -> void:
2025-04-23 15:37:03 +02:00
var current_levels := get_current_levels()
if len(current_levels) && !changing_level:
pause_game(false)
changing_level = true
for level in current_levels:
level.queue_free()
start_level(levels[current_level_int])
func start_game() -> void:
current_level_int = 0
var current_levels = $Levels.get_children(true)
for level in current_levels:
level.queue_free()
$GUI.show()
Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)
start_level(levels[current_level_int])
func pause_game(to_pause: bool) -> void:
if !len(get_current_levels()) or changing_level:
return
SaveFiles.change_property(\"played_for\", gui_timer.seconds_spent_total, SaveFiles.selected_file)
if to_pause:
2025-02-23 16:18:14 +01:00
$Levels.process_mode = Node.PROCESS_MODE_DISABLED
2025-03-25 17:48:00 +01:00
playing = false
2025-04-23 15:37:03 +02:00
pause_menu.show()
2025-02-23 16:18:14 +01:00
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
else:
$Levels.process_mode = Node.PROCESS_MODE_INHERIT
2025-03-25 17:48:00 +01:00
playing = true
2025-04-23 15:37:03 +02:00
pause_menu.hide()
2025-02-23 16:18:14 +01:00
Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)
func fullscreen_game() -> void:
2025-02-23 00:46:23 +01:00
var fs = DisplayServer.window_get_mode()
if fs != DisplayServer.WindowMode.WINDOW_MODE_FULLSCREEN:
DisplayServer.window_set_mode(DisplayServer.WindowMode.WINDOW_MODE_FULLSCREEN)
else:
DisplayServer.window_set_mode(DisplayServer.WindowMode.WINDOW_MODE_WINDOWED)
2025-04-20 23:25:51 +02:00
func _process(_delta: float) -> void:
2025-03-25 17:48:00 +01:00
var current_levels = get_current_levels()
2025-02-23 14:27:35 +01:00
if len(current_levels):
var current_level = current_levels[0]
2025-04-23 15:37:03 +02:00
gui_speed.ball_velocity = current_level.velocity
func _input(_event: InputEvent) -> void:
if Input.is_action_just_pressed(\"restart_level\"):
restart_level()
2025-02-23 16:18:14 +01:00
func _on_btn_quit_pressed() -> void:
get_tree().quit()
2025-02-23 00:46:23 +01:00
"
2025-02-23 17:21:13 +01:00
[sub_resource type="LabelSettings" id="LabelSettings_1bs00"]
font_size = 160
outline_size = 20
outline_color = Color(0, 0, 0, 1)
2025-02-22 00:19:28 +01:00
[node name="Game" type="Node"]
2025-02-23 00:46:23 +01:00
script = SubResource("GDScript_8n212")
2025-04-21 16:06:56 +02:00
[node name="GUI" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 1
[node name="TopLeft" type="MarginContainer" parent="GUI"]
layout_mode = 1
offset_right = 160.0
offset_bottom = 85.0
2025-04-20 23:25:51 +02:00
rotation = 0.0523599
theme_override_constants/margin_left = 15
2025-04-21 16:06:56 +02:00
[node name="Timer" parent="GUI/TopLeft" instance=ExtResource("1_356j3")]
layout_mode = 2
[node name="TopRight" type="MarginContainer" parent="GUI"]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -106.0
offset_bottom = 51.0
grow_horizontal = 0
rotation = -0.0523599
theme_override_constants/margin_top = 5
2025-04-20 23:25:51 +02:00
theme_override_constants/margin_right = 15
2025-04-21 16:06:56 +02:00
[node name="Speed" parent="GUI/TopRight" instance=ExtResource("2_2gn6w")]
2025-04-20 23:25:51 +02:00
layout_mode = 2
2025-04-23 15:37:03 +02:00
[node name="BottomRight" type="MarginContainer" parent="GUI"]
2025-02-23 14:27:35 +01:00
layout_mode = 1
2025-04-23 15:37:03 +02:00
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
2025-02-23 14:27:35 +01:00
anchor_right = 1.0
anchor_bottom = 1.0
2025-04-23 15:37:03 +02:00
offset_left = -222.0
offset_top = -51.0
grow_horizontal = 0
grow_vertical = 0
rotation = 0.0523599
theme_override_constants/margin_right = 15
theme_override_constants/margin_bottom = 15
2025-02-23 14:27:35 +01:00
2025-04-23 15:37:03 +02:00
[node name="Rings" parent="GUI/BottomRight" instance=ExtResource("3_mbj17")]
2025-02-23 14:27:35 +01:00
layout_mode = 2
2025-02-23 17:21:13 +01:00
[node name="VictoryScreen" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Label" type="Label" parent="VictoryScreen"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
text = "YOU WON!"
label_settings = SubResource("LabelSettings_1bs00")
horizontal_alignment = 1
vertical_alignment = 1
[node name="Levels" type="Node" parent="."]
2025-04-23 15:37:03 +02:00
[node name="PauseMenu" parent="." instance=ExtResource("4_3bfj3")]
2025-02-23 16:18:14 +01:00
2025-03-30 15:40:22 +02:00
[node name="DevInfos" type="Label" parent="."]
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = -23.0
grow_horizontal = 2
grow_vertical = 0
horizontal_alignment = 1