Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added level loading screen (reference issue #190) #191

Merged
merged 18 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ size_flags_horizontal = 4
size_flags_vertical = 4
theme_override_constants/separation = 8
script = ExtResource("2_wft4x")
search_depth = 2
search_depth = 4

[node name="InputMappingContainer" type="VBoxContainer" parent="VBoxContainer"]
layout_mode = 2
Expand Down
6 changes: 5 additions & 1 deletion addons/maaacks_game_template/base/scripts/capture_focus.gd
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class_name CaptureFocus
extends Container
extends Control
## Node that captures UI focus for games with a hidden mouse or joypad enabled.
##
## This script assists with capturing UI focus when
Expand All @@ -11,6 +11,7 @@ extends Container
## Hierarchical depth to search in the scene tree.
@export var search_depth : int = 1
@export var enabled : bool = false
@export var null_focus_enabled : bool = true
@export var joypad_enabled : bool = true
@export var mouse_hidden_enabled : bool = true

Expand All @@ -27,6 +28,8 @@ func _focus_first_search(control_node : Control, levels : int = 1):
return false
if control_node.focus_mode == FOCUS_ALL:
control_node.grab_focus()
if control_node is ItemList:
control_node.select(0)
return true
if levels < 1:
return false
Expand All @@ -45,6 +48,7 @@ func update_focus():

func _should_capture_focus():
return enabled or \
(get_viewport().gui_get_focus_owner() == null and null_focus_enabled) or \
(Input.get_connected_joypads().size() > 0 and joypad_enabled) or \
(Input.mouse_mode not in [Input.MOUSE_MODE_VISIBLE, Input.MOUSE_MODE_CONFINED] and mouse_hidden_enabled)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
extends Control

## Loads a simple ItemList node within a margin container. SceneLister updates
## the available scenes in the directory provided. Activating a level will update
## the GameState's current_level, and emit a signal. The main menu node will trigger
## a load action from that signal.

@onready var level_buttons_container: ItemList = %LevelButtonsContainer
@onready var scene_lister: SceneLister = $SceneLister

signal level_selected

func _ready() -> void:
add_levels_to_container()

## A fresh level list is propgated into the ItemList, and the file names are cleaned
func add_levels_to_container():
level_buttons_container.clear()
var max_level_reached := GameStateExample.get_max_level_reached()
var level_iter := 0
for file_path in scene_lister.files:
if level_iter > max_level_reached : break
level_iter += 1
# Extract the file name from the path
var file_name = file_path.get_file() # e.g., "level_1.tscn"
# Clean up the file name
file_name = file_name.trim_suffix(".tscn") # Remove the ".tscn" extension
file_name = file_name.replace("_", " ") # Replace underscores with spaces
file_name = file_name.capitalize() # Convert to proper case
var button_name = str(file_name)
level_buttons_container.add_item(button_name)

func _on_level_buttons_container_item_activated(index: int) -> void:
GameStateExample.set_current_level(index)
level_selected.emit()
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[gd_scene load_steps=4 format=3 uid="uid://dtu0ffm1m5mr7"]

[ext_resource type="Script" path="res://addons/maaacks_game_template/examples/scenes/menus/level_select_menu/level_select_menu.gd" id="1_dm7vg"]
[ext_resource type="Script" path="res://addons/maaacks_game_template/base/scripts/capture_focus.gd" id="2_88qak"]
[ext_resource type="Script" path="res://addons/maaacks_game_template/extras/scripts/scene_lister.gd" id="2_g3cvb"]

[node name="LevelSelectMenu" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_dm7vg")

[node name="Control" type="Control" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("2_88qak")

[node name="LevelButtonsContainer" type="ItemList" parent="Control"]
unique_name_in_owner = true
custom_minimum_size = Vector2(400, 0)
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -200.0
offset_top = -17.5
offset_right = 200.0
offset_bottom = 17.5
grow_horizontal = 2
grow_vertical = 2
auto_height = true
item_count = 1
item_0/text = "1 - ExampleLevel"

[node name="SceneLister" type="Node" parent="."]
script = ExtResource("2_g3cvb")
files = Array[String](["res://addons/maaacks_game_template/examples/scenes/game_scene/levels/level_1.tscn", "res://addons/maaacks_game_template/examples/scenes/game_scene/levels/level_2.tscn", "res://addons/maaacks_game_template/examples/scenes/game_scene/levels/level_3.tscn"])
directory = "res://addons/maaacks_game_template/examples/scenes/game_scene/levels"

[connection signal="item_activated" from="Control/LevelButtonsContainer" to="." method="_on_level_buttons_container_item_activated"]
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
extends MainMenu

@export var level_select_packed_scene: PackedScene

var level_select_scene
var animation_state_machine : AnimationNodeStateMachinePlayback

func load_game_scene():
Expand Down Expand Up @@ -33,6 +36,14 @@ func _close_sub_menu():
super._close_sub_menu()
animation_state_machine.travel("OpenMainMenu")

func _setup_level_select():
if level_select_packed_scene != null:
level_select_scene = level_select_packed_scene.instantiate()
level_select_scene.hide()
%LevelSelectContainer.call_deferred("add_child", level_select_scene)
if level_select_scene.has_signal("level_selected"):
level_select_scene.connect("level_selected", load_game_scene)

func _input(event):
if _is_in_intro() and _event_skips_intro(event):
intro_done()
Expand All @@ -41,12 +52,18 @@ func _input(event):

func _ready():
super._ready()
_setup_level_select()
animation_state_machine = $MenuAnimationTree.get("parameters/playback")

func _setup_game_buttons():
super._setup_game_buttons()
if GameStateExample.has_game_state():
%ContinueGameButton.show()
if GameStateExample.get_max_level_reached() > 0:
%LevelSelectButton.show()

func _on_continue_game_button_pressed():
load_game_scene()

func _on_level_select_button_pressed():
_open_sub_menu(level_select_scene)
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
[gd_scene load_steps=18 format=3 uid="uid://c63y6b25bs4bk"]
[gd_scene load_steps=19 format=3 uid="uid://c63y6b25bs4bk"]

[ext_resource type="PackedScene" uid="uid://c6k5nnpbypshi" path="res://addons/maaacks_game_template/base/scenes/menus/main_menu/main_menu.tscn" id="1_0i2sc"]
[ext_resource type="Script" path="res://addons/maaacks_game_template/examples/scenes/menus/main_menu/main_menu_with_animations.gd" id="2_ncvk7"]
[ext_resource type="PackedScene" uid="uid://bdvdf5v87mmrr" path="res://addons/maaacks_game_template/examples/scenes/menus/options_menu/master_options_menu_with_tabs.tscn" id="3_tuy3s"]
[ext_resource type="PackedScene" uid="uid://c1g50h2avck3w" path="res://addons/maaacks_game_template/examples/scenes/credits/credits.tscn" id="4_lwsll"]
[ext_resource type="PackedScene" uid="uid://dtu0ffm1m5mr7" path="res://addons/maaacks_game_template/examples/scenes/menus/level_select_menu/level_select_menu.tscn" id="5_4pbct"]

[sub_resource type="Animation" id="1"]
resource_name = "Intro"
Expand Down Expand Up @@ -351,6 +352,7 @@ graph_offset = Vector2(-180.277, 49)

[node name="MainMenu" instance=ExtResource("1_0i2sc")]
script = ExtResource("2_ncvk7")
level_select_packed_scene = ExtResource("5_4pbct")
game_scene_path = "res://addons/maaacks_game_template/examples/scenes/game_scene/game_ui.tscn"
options_packed_scene = ExtResource("3_tuy3s")
credits_packed_scene = ExtResource("4_lwsll")
Expand All @@ -371,6 +373,9 @@ modulate = Color(1, 1, 1, 0)
[node name="TitleContainer" parent="MenuContainer/TitleMargin" index="0"]
modulate = Color(1, 1, 1, 0)

[node name="TitleLabel" parent="MenuContainer/TitleMargin/TitleContainer" index="0"]
text = "Game Template"

[node name="SubTitleContainer" parent="MenuContainer/SubTitleMargin" index="0"]
modulate = Color(1, 1, 1, 0)

Expand All @@ -387,4 +392,23 @@ custom_minimum_size = Vector2(128, 40)
layout_mode = 2
text = "Continue"

[node name="LevelSelectButton" type="Button" parent="MenuContainer/MenuButtonsMargin/MenuButtonsContainer/MenuButtonsBoxContainer" index="2"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(128, 40)
layout_mode = 2
text = "Level Select"

[node name="LevelSelectContainer" type="MarginContainer" parent="." index="9"]
unique_name_in_owner = true
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
theme_override_constants/margin_left = 16
theme_override_constants/margin_top = 32
theme_override_constants/margin_right = 16
theme_override_constants/margin_bottom = 32

[connection signal="pressed" from="MenuContainer/MenuButtonsMargin/MenuButtonsContainer/MenuButtonsBoxContainer/ContinueGameButton" to="." method="_on_continue_game_button_pressed"]
[connection signal="pressed" from="MenuContainer/MenuButtonsMargin/MenuButtonsContainer/MenuButtonsBoxContainer/LevelSelectButton" to="." method="_on_level_select_button_pressed"]
6 changes: 6 additions & 0 deletions addons/maaacks_game_template/examples/scripts/game_state.gd
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ static func get_current_level() -> int:
return 0
return game_state.current_level

static func get_max_level_reached() -> int:
var game_state = get_game_state()
if not game_state:
return 0
return game_state.max_level_reached

static func level_reached(level_number):
var game_state = get_game_state()
if not game_state:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ func set_current_level_id(value):
GameStateExample.level_reached(value)

func get_current_level_id() -> int:
return GameStateExample.get_current_level() if force_level == -1 else force_level
current_level_id = GameStateExample.get_current_level() if force_level == -1 else force_level
return current_level_id

func _advance_level():
super._advance_level()
Expand Down
35 changes: 35 additions & 0 deletions scenes/menus/level_select_menu/level_select_menu.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
extends Control

## Loads a simple ItemList node within a margin container. SceneLister updates
## the available scenes in the directory provided. Activating a level will update
## the GameState's current_level, and emit a signal. The main menu node will trigger
## a load action from that signal.

@onready var level_buttons_container: ItemList = %LevelButtonsContainer
@onready var scene_lister: SceneLister = $SceneLister

signal level_selected

func _ready() -> void:
add_levels_to_container()

## A fresh level list is propgated into the ItemList, and the file names are cleaned
func add_levels_to_container():
level_buttons_container.clear()
var max_level_reached := GameState.get_max_level_reached()
var level_iter := 0
for file_path in scene_lister.files:
if level_iter > max_level_reached : break
level_iter += 1
# Extract the file name from the path
var file_name = file_path.get_file() # e.g., "level_1.tscn"
# Clean up the file name
file_name = file_name.trim_suffix(".tscn") # Remove the ".tscn" extension
file_name = file_name.replace("_", " ") # Replace underscores with spaces
file_name = file_name.capitalize() # Convert to proper case
var button_name = str(file_name)
level_buttons_container.add_item(button_name)

func _on_level_buttons_container_item_activated(index: int) -> void:
GameState.set_current_level(index)
level_selected.emit()
49 changes: 49 additions & 0 deletions scenes/menus/level_select_menu/level_select_menu.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[gd_scene load_steps=4 format=3 uid="uid://crgwq4t7ljint"]

[ext_resource type="Script" path="res://scenes/menus/level_select_menu/level_select_menu.gd" id="1_h6hut"]
[ext_resource type="Script" path="res://addons/maaacks_game_template/base/scripts/capture_focus.gd" id="2_c723y"]
[ext_resource type="Script" path="res://addons/maaacks_game_template/extras/scripts/scene_lister.gd" id="3_odcm1"]

[node name="LevelSelectMenu" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_h6hut")

[node name="Control" type="Control" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("2_c723y")

[node name="LevelButtonsContainer" type="ItemList" parent="Control"]
unique_name_in_owner = true
custom_minimum_size = Vector2(400, 0)
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -200.0
offset_top = -17.5
offset_right = 200.0
offset_bottom = 17.5
grow_horizontal = 2
grow_vertical = 2
auto_height = true
item_count = 1
item_0/text = "1 - ExampleLevel"

[node name="SceneLister" type="Node" parent="."]
script = ExtResource("3_odcm1")
files = Array[String](["res://scenes/game_scene/levels/level_1.tscn", "res://scenes/game_scene/levels/level_2.tscn", "res://scenes/game_scene/levels/level_3.tscn"])
directory = "res://scenes/game_scene/levels"

[connection signal="item_activated" from="Control/LevelButtonsContainer" to="." method="_on_level_buttons_container_item_activated"]
17 changes: 17 additions & 0 deletions scenes/menus/main_menu/main_menu_with_animations.gd
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
extends MainMenu

@export var level_select_packed_scene: PackedScene

var level_select_scene
var animation_state_machine : AnimationNodeStateMachinePlayback

func load_game_scene():
Expand Down Expand Up @@ -33,6 +36,14 @@ func _close_sub_menu():
super._close_sub_menu()
animation_state_machine.travel("OpenMainMenu")

func _setup_level_select():
if level_select_packed_scene != null:
level_select_scene = level_select_packed_scene.instantiate()
level_select_scene.hide()
%LevelSelectContainer.call_deferred("add_child", level_select_scene)
if level_select_scene.has_signal("level_selected"):
level_select_scene.connect("level_selected", load_game_scene)

func _input(event):
if _is_in_intro() and _event_skips_intro(event):
intro_done()
Expand All @@ -41,12 +52,18 @@ func _input(event):

func _ready():
super._ready()
_setup_level_select()
animation_state_machine = $MenuAnimationTree.get("parameters/playback")

func _setup_game_buttons():
super._setup_game_buttons()
if GameState.has_game_state():
%ContinueGameButton.show()
if GameState.get_max_level_reached() > 0:
%LevelSelectButton.show()

func _on_continue_game_button_pressed():
load_game_scene()

func _on_level_select_button_pressed():
_open_sub_menu(level_select_scene)
Loading