gd: added menu template
This commit is contained in:
@ -0,0 +1,34 @@
|
||||
class_name GameWonMenu
|
||||
extends OverlaidMenu
|
||||
|
||||
signal continue_pressed
|
||||
signal main_menu_pressed
|
||||
|
||||
func _handle_cancel_input():
|
||||
if $ConfirmExit.visible:
|
||||
$ConfirmExit.hide()
|
||||
elif $ConfirmMainMenu.visible:
|
||||
$ConfirmMainMenu.hide()
|
||||
else:
|
||||
super._handle_cancel_input()
|
||||
|
||||
func _ready():
|
||||
if OS.has_feature("web"):
|
||||
%ExitButton.hide()
|
||||
|
||||
func _on_exit_button_pressed():
|
||||
$ConfirmExit.popup_centered()
|
||||
|
||||
func _on_main_menu_button_pressed():
|
||||
$ConfirmMainMenu.popup_centered()
|
||||
|
||||
func _on_confirm_main_menu_confirmed():
|
||||
main_menu_pressed.emit()
|
||||
close()
|
||||
|
||||
func _on_confirm_exit_confirmed():
|
||||
get_tree().quit()
|
||||
|
||||
func _on_close_button_pressed():
|
||||
continue_pressed.emit()
|
||||
close()
|
@ -0,0 +1 @@
|
||||
uid://gi8tms6wsj1n
|
@ -0,0 +1,61 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://4brssbq1ghsw"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://wny2d8dvp3ok" path="res://addons/maaacks_game_template/base/scenes/overlaid_menu/overlaid_menu.tscn" id="1_87sd7"]
|
||||
[ext_resource type="Script" uid="uid://gi8tms6wsj1n" path="res://addons/maaacks_game_template/extras/scenes/overlaid_menus/game_won_menu.gd" id="2_hi7oy"]
|
||||
|
||||
[node name="GameWonMenu" instance=ExtResource("1_87sd7")]
|
||||
process_mode = 3
|
||||
script = ExtResource("2_hi7oy")
|
||||
pauses_game = true
|
||||
|
||||
[node name="MenuPanelContainer" parent="." index="1"]
|
||||
custom_minimum_size = Vector2(432, 240)
|
||||
|
||||
[node name="TitleMargin" parent="MenuPanelContainer/MarginContainer/BoxContainer" index="0"]
|
||||
visible = false
|
||||
|
||||
[node name="DescriptionMargin" parent="MenuPanelContainer/MarginContainer/BoxContainer" index="1"]
|
||||
visible = true
|
||||
theme_override_constants/margin_top = 64
|
||||
theme_override_constants/margin_bottom = 64
|
||||
|
||||
[node name="DescriptionLabel" parent="MenuPanelContainer/MarginContainer/BoxContainer/DescriptionMargin" index="0"]
|
||||
text = "[center]You won![/center]"
|
||||
scroll_active = false
|
||||
|
||||
[node name="MenuButtons" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin" index="0"]
|
||||
custom_minimum_size = Vector2(400, 0)
|
||||
vertical = false
|
||||
|
||||
[node name="ExitButton" type="Button" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons" index="0"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Exit"
|
||||
|
||||
[node name="MainMenuButton" type="Button" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons" index="1"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Main Menu"
|
||||
|
||||
[node name="CloseButton" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons" index="2"]
|
||||
size_flags_horizontal = 3
|
||||
text = "Continue"
|
||||
|
||||
[node name="ConfirmMainMenu" type="ConfirmationDialog" parent="." index="2"]
|
||||
auto_translate_mode = 1
|
||||
initial_position = 2
|
||||
dialog_text = "Go back to main menu?"
|
||||
|
||||
[node name="ConfirmExit" type="ConfirmationDialog" parent="." index="3"]
|
||||
auto_translate_mode = 1
|
||||
initial_position = 2
|
||||
dialog_text = "Quit the game?"
|
||||
|
||||
[connection signal="pressed" from="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons/ExitButton" to="." method="_on_exit_button_pressed"]
|
||||
[connection signal="pressed" from="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons/MainMenuButton" to="." method="_on_main_menu_button_pressed"]
|
||||
[connection signal="confirmed" from="ConfirmMainMenu" to="." method="_on_confirm_main_menu_confirmed"]
|
||||
[connection signal="confirmed" from="ConfirmExit" to="." method="_on_confirm_exit_confirmed"]
|
@ -0,0 +1,34 @@
|
||||
class_name LevelLostMenu
|
||||
extends OverlaidMenu
|
||||
|
||||
signal restart_pressed
|
||||
signal main_menu_pressed
|
||||
|
||||
func _handle_cancel_input():
|
||||
if $ConfirmExit.visible:
|
||||
$ConfirmExit.hide()
|
||||
elif $ConfirmMainMenu.visible:
|
||||
$ConfirmMainMenu.hide()
|
||||
else:
|
||||
super._handle_cancel_input()
|
||||
|
||||
func _ready():
|
||||
if OS.has_feature("web"):
|
||||
%ExitButton.hide()
|
||||
|
||||
func _on_exit_button_pressed():
|
||||
$ConfirmExit.popup_centered()
|
||||
|
||||
func _on_main_menu_button_pressed():
|
||||
$ConfirmMainMenu.popup_centered()
|
||||
|
||||
func _on_confirm_main_menu_confirmed():
|
||||
main_menu_pressed.emit()
|
||||
close()
|
||||
|
||||
func _on_confirm_exit_confirmed():
|
||||
get_tree().quit()
|
||||
|
||||
func _on_close_button_pressed():
|
||||
restart_pressed.emit()
|
||||
close()
|
@ -0,0 +1 @@
|
||||
uid://ckh3w3xa6qjk0
|
@ -0,0 +1,59 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dkq3nhkmhu4je"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://wny2d8dvp3ok" path="res://addons/maaacks_game_template/base/scenes/overlaid_menu/overlaid_menu.tscn" id="1_ok347"]
|
||||
[ext_resource type="Script" uid="uid://ckh3w3xa6qjk0" path="res://addons/maaacks_game_template/extras/scenes/overlaid_menus/level_lost_menu.gd" id="2_6r1n8"]
|
||||
|
||||
[node name="LevelLostMenu" instance=ExtResource("1_ok347")]
|
||||
process_mode = 3
|
||||
script = ExtResource("2_6r1n8")
|
||||
pauses_game = true
|
||||
|
||||
[node name="MenuPanelContainer" parent="." index="1"]
|
||||
custom_minimum_size = Vector2(432, 240)
|
||||
|
||||
[node name="TitleMargin" parent="MenuPanelContainer/MarginContainer/BoxContainer" index="0"]
|
||||
visible = false
|
||||
|
||||
[node name="DescriptionMargin" parent="MenuPanelContainer/MarginContainer/BoxContainer" index="1"]
|
||||
visible = true
|
||||
theme_override_constants/margin_top = 64
|
||||
theme_override_constants/margin_bottom = 64
|
||||
|
||||
[node name="DescriptionLabel" parent="MenuPanelContainer/MarginContainer/BoxContainer/DescriptionMargin" index="0"]
|
||||
text = "[center]You lost...[/center]"
|
||||
scroll_active = false
|
||||
|
||||
[node name="MenuButtons" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin" index="0"]
|
||||
custom_minimum_size = Vector2(400, 0)
|
||||
vertical = false
|
||||
|
||||
[node name="ExitButton" type="Button" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons" index="0"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Exit"
|
||||
|
||||
[node name="MainMenuButton" type="Button" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons" index="1"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Main Menu"
|
||||
|
||||
[node name="CloseButton" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons" index="2"]
|
||||
size_flags_horizontal = 3
|
||||
text = "Restart"
|
||||
|
||||
[node name="ConfirmMainMenu" type="ConfirmationDialog" parent="." index="2"]
|
||||
auto_translate_mode = 1
|
||||
initial_position = 2
|
||||
dialog_text = "Go back to main menu?"
|
||||
|
||||
[node name="ConfirmExit" type="ConfirmationDialog" parent="." index="3"]
|
||||
auto_translate_mode = 1
|
||||
initial_position = 2
|
||||
dialog_text = "Quit the game?"
|
||||
|
||||
[connection signal="pressed" from="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons/ExitButton" to="." method="_on_exit_button_pressed"]
|
||||
[connection signal="pressed" from="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons/MainMenuButton" to="." method="_on_main_menu_button_pressed"]
|
||||
[connection signal="confirmed" from="ConfirmMainMenu" to="." method="_on_confirm_main_menu_confirmed"]
|
||||
[connection signal="confirmed" from="ConfirmExit" to="." method="_on_confirm_exit_confirmed"]
|
@ -0,0 +1,27 @@
|
||||
class_name LevelWonMenu
|
||||
extends OverlaidMenu
|
||||
|
||||
signal continue_pressed
|
||||
signal restart_pressed
|
||||
signal main_menu_pressed
|
||||
|
||||
func _input(event):
|
||||
if event.is_action_pressed("ui_cancel"):
|
||||
if $ConfirmMainMenu.visible:
|
||||
$ConfirmMainMenu.hide()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func _on_main_menu_button_pressed():
|
||||
$ConfirmMainMenu.popup_centered()
|
||||
|
||||
func _on_confirm_main_menu_confirmed():
|
||||
main_menu_pressed.emit()
|
||||
close()
|
||||
|
||||
func _on_restart_button_pressed():
|
||||
restart_pressed.emit()
|
||||
close()
|
||||
|
||||
func _on_close_button_pressed():
|
||||
continue_pressed.emit()
|
||||
close()
|
@ -0,0 +1 @@
|
||||
uid://bdic7jebf0y7a
|
@ -0,0 +1,53 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://y3vtx0e0shv4"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://wny2d8dvp3ok" path="res://addons/maaacks_game_template/base/scenes/overlaid_menu/overlaid_menu.tscn" id="1_nknag"]
|
||||
[ext_resource type="Script" uid="uid://bdic7jebf0y7a" path="res://addons/maaacks_game_template/extras/scenes/overlaid_menus/level_won_menu.gd" id="2_klq7f"]
|
||||
|
||||
[node name="LevelWonMenu" instance=ExtResource("1_nknag")]
|
||||
process_mode = 3
|
||||
script = ExtResource("2_klq7f")
|
||||
pauses_game = true
|
||||
|
||||
[node name="MenuPanelContainer" parent="." index="1"]
|
||||
custom_minimum_size = Vector2(432, 240)
|
||||
|
||||
[node name="TitleMargin" parent="MenuPanelContainer/MarginContainer/BoxContainer" index="0"]
|
||||
visible = false
|
||||
|
||||
[node name="DescriptionMargin" parent="MenuPanelContainer/MarginContainer/BoxContainer" index="1"]
|
||||
visible = true
|
||||
theme_override_constants/margin_top = 64
|
||||
theme_override_constants/margin_bottom = 64
|
||||
|
||||
[node name="DescriptionLabel" parent="MenuPanelContainer/MarginContainer/BoxContainer/DescriptionMargin" index="0"]
|
||||
text = "[center]Level complete![/center]"
|
||||
scroll_active = false
|
||||
|
||||
[node name="MenuButtons" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin" index="0"]
|
||||
custom_minimum_size = Vector2(400, 0)
|
||||
vertical = false
|
||||
|
||||
[node name="MainMenuButton" type="Button" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons" index="0"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Main Menu"
|
||||
|
||||
[node name="RestartButton" type="Button" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons" index="1"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Restart"
|
||||
|
||||
[node name="CloseButton" parent="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons" index="2"]
|
||||
size_flags_horizontal = 3
|
||||
text = "Continue"
|
||||
|
||||
[node name="ConfirmMainMenu" type="ConfirmationDialog" parent="." index="2"]
|
||||
auto_translate_mode = 1
|
||||
initial_position = 2
|
||||
dialog_text = "Go back to main menu?"
|
||||
|
||||
[connection signal="pressed" from="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons/MainMenuButton" to="." method="_on_main_menu_button_pressed"]
|
||||
[connection signal="pressed" from="MenuPanelContainer/MarginContainer/BoxContainer/MenuButtonsMargin/MenuButtons/RestartButton" to="." method="_on_restart_button_pressed"]
|
||||
[connection signal="confirmed" from="ConfirmMainMenu" to="." method="_on_confirm_main_menu_confirmed"]
|
70
addons/maaacks_game_template/extras/scripts/asset_checker.sh
Normal file
70
addons/maaacks_game_template/extras/scripts/asset_checker.sh
Normal file
@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
# asset checker command
|
||||
# Used for quickly checking that assets (like audio files) are being used where expected.
|
||||
#
|
||||
# Recursively searches through scene files (.tscn, .scn, .res)
|
||||
# for occurrences of asset types (default: AudioStream).
|
||||
# It then outputs the paths of assets discovered,
|
||||
# along with the file names that use them.
|
||||
|
||||
short_flag=false
|
||||
asset_type="AudioStream"
|
||||
|
||||
print_usage() {
|
||||
printf "Usage: -sa %s\n" "$asset_type"
|
||||
}
|
||||
|
||||
while getopts 'a:s' flag; do
|
||||
case "${flag}" in
|
||||
a)
|
||||
asset_type="${OPTARG}"
|
||||
;;
|
||||
s)
|
||||
short_flag=true
|
||||
;;
|
||||
*)
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Initialize an associative array to store paths and corresponding files
|
||||
declare -A path_files
|
||||
|
||||
while IFS=: read -r file line; do
|
||||
path=$(echo "$line" | grep -o 'path="[^"]*' | cut -d'"' -f2)
|
||||
if [ -n "$path" ]; then
|
||||
# Append the current file to the string of files for this path
|
||||
# Note: Bash does not support having arrays as values of associative array.
|
||||
# Using a pipe `|` separator instead, and then splitting on output
|
||||
if [ -z "${path_files["$path"]}" ]; then
|
||||
path_files["$path"]=$file
|
||||
else
|
||||
path_files["$path"]+="|$file"
|
||||
fi
|
||||
fi
|
||||
done < <(egrep -ir --include=*.{tscn,scn,res} "type=\"$asset_type\"")
|
||||
|
||||
# Get the paths and sort them
|
||||
sorted_paths=()
|
||||
for key in "${!path_files[@]}"; do
|
||||
sorted_paths+=("$key")
|
||||
done
|
||||
IFS=$'\n' sorted_paths=($(sort <<< "${sorted_paths[*]}"))
|
||||
unset IFS
|
||||
|
||||
# Print out the results
|
||||
for path in "${sorted_paths[@]}"; do
|
||||
# Note: Bash does not support having arrays as values of associative array.
|
||||
# Splitting the concatenated files string on the pipe `|` separator.
|
||||
IFS='|' read -r -a files_array <<< "${path_files[$path]}"
|
||||
files_count=${#files_array[@]}
|
||||
printf "%-80s | Uses: %s\n" "$path" "$files_count"
|
||||
if ! $short_flag ; then
|
||||
for file in "${files_array[@]}"; do
|
||||
printf "\t%82s\n" "$file"
|
||||
done
|
||||
echo
|
||||
fi
|
||||
done
|
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
# butler manager command
|
||||
# Uploads directories as builds to matching itch.io channels.
|
||||
# HTML5 => html5
|
||||
# Linux => linux
|
||||
# Windows => win
|
||||
# MacOS => osx
|
||||
|
||||
file=upload_destination.txt
|
||||
directories=("HTML5" "Linux" "Windows" "MacOS")
|
||||
channels=("html5" "linux" "win" "osx")
|
||||
|
||||
# Check if the file exists
|
||||
if [ ! -e $file ]; then
|
||||
# File doesn't exist, create an empty one
|
||||
touch $file
|
||||
fi
|
||||
|
||||
# File exists, read the first line into a variable
|
||||
read -r destination < $file
|
||||
|
||||
if [ -z "$destination" ]; then
|
||||
# File is empty, prompt the user for input
|
||||
echo "Please enter the build destination (username/project-url-after-slash)."
|
||||
read -r user_input
|
||||
|
||||
# Save user input to the file
|
||||
echo "$user_input" > "$file"
|
||||
echo "Destination saved to $file."
|
||||
destination="$user_input"
|
||||
fi
|
||||
|
||||
# Check for the existence of directories and upload contents
|
||||
for ((i=0; i<${#directories[@]}; i++)); do
|
||||
dir="${directories[i]}"
|
||||
channel="${channels[i]}"
|
||||
|
||||
if [ -d "$dir" ]; then
|
||||
echo butler push ./$dir/ $destination:$channel
|
||||
butler push ./$dir/ $destination:$channel
|
||||
else
|
||||
echo "Directory '$dir' does not exist."
|
||||
fi
|
||||
done
|
@ -0,0 +1,9 @@
|
||||
class_name CaptureMouse
|
||||
extends Control
|
||||
## Control node that captures the mouse for games that require it.
|
||||
##
|
||||
## Used for games that use the mouse to move the camera (ex. FPS or third-person shooters).
|
||||
|
||||
func _gui_input(event):
|
||||
if event is InputEventMouseButton and Input.mouse_mode != Input.MOUSE_MODE_CAPTURED:
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
@ -0,0 +1 @@
|
||||
uid://dqdyrkm3jily6
|
@ -0,0 +1,48 @@
|
||||
@tool
|
||||
class_name LevelListLoader
|
||||
extends SceneLister
|
||||
## Extends [SceneLister] to manage level advancement through [GameStateExample].
|
||||
|
||||
signal level_load_started
|
||||
signal level_loaded
|
||||
signal levels_finished
|
||||
|
||||
## Container where the level instance will be added.
|
||||
@export var level_container : Node
|
||||
|
||||
var current_level : Node
|
||||
|
||||
func get_level_file(level_id : int):
|
||||
if files.is_empty():
|
||||
push_error("levels list is empty")
|
||||
return
|
||||
if level_id >= files.size():
|
||||
push_error("level_id is out of bounds of the levels list")
|
||||
level_id = files.size() - 1
|
||||
return files[level_id]
|
||||
|
||||
func _attach_level(level_resource : Resource):
|
||||
assert(level_container != null, "level_container is null")
|
||||
var instance = level_resource.instantiate()
|
||||
level_container.call_deferred("add_child", instance)
|
||||
return instance
|
||||
|
||||
func load_level(level_id : int):
|
||||
if is_instance_valid(current_level):
|
||||
current_level.queue_free()
|
||||
await current_level.tree_exited
|
||||
current_level = null
|
||||
var level_file = get_level_file(level_id)
|
||||
if level_file == null:
|
||||
levels_finished.emit()
|
||||
return
|
||||
SceneLoader.load_scene(level_file, true)
|
||||
level_load_started.emit()
|
||||
await SceneLoader.scene_loaded
|
||||
current_level = _attach_level(SceneLoader.get_resource())
|
||||
level_loaded.emit()
|
||||
|
||||
func _ready():
|
||||
if Engine.is_editor_hint():
|
||||
# Text files get a `.remap` extension added on export.
|
||||
_refresh_files()
|
@ -0,0 +1 @@
|
||||
uid://crbo2e4ndbyvk
|
@ -0,0 +1,143 @@
|
||||
class_name LevelListManager
|
||||
extends Node
|
||||
## Manager of level progress and the result screens between them.
|
||||
##
|
||||
## A helper script to assign to a node in a scene.
|
||||
## It works with a level list loader and a loading screen
|
||||
## to advance levels and open menus when players win or lose.
|
||||
|
||||
## Required reference to a level list loader in the scene.
|
||||
@export var level_list_loader : LevelListLoader
|
||||
## Required path to a main menu scene.
|
||||
@export_file("*.tscn") var main_menu_scene : String
|
||||
## Optional path to an ending scene.
|
||||
@export_file("*.tscn") var ending_scene : String
|
||||
@export var auto_load : bool = true
|
||||
@export_group("Screens")
|
||||
## Optional reference to a loading screen in the scene.
|
||||
@export var level_loading_screen : LoadingScreen
|
||||
## Optional win screen to be shown after the last level is won.
|
||||
@export var game_won_scene : PackedScene
|
||||
## Optional lose screen to be shown after the level is lost.
|
||||
@export var level_lost_scene : PackedScene
|
||||
## Optional level compete screen to be shown after the level is won.
|
||||
@export var level_won_scene : PackedScene
|
||||
## Loads a level on start.
|
||||
@export_group("Debugging")
|
||||
@export var force_level : int = -1
|
||||
|
||||
## Reference to the current level node.
|
||||
var current_level
|
||||
var current_level_id : int :
|
||||
set = set_current_level_id
|
||||
|
||||
func set_current_level_id(value : int) -> void:
|
||||
current_level_id = value
|
||||
|
||||
func _try_connecting_signal_to_node(node : Node, signal_name : String, callable : Callable) -> void:
|
||||
if node.has_signal(signal_name) and not node.is_connected(signal_name, callable):
|
||||
node.connect(signal_name, callable)
|
||||
|
||||
func _try_connecting_signal_to_level(signal_name : String, callable : Callable) -> void:
|
||||
_try_connecting_signal_to_node(current_level, signal_name, callable)
|
||||
|
||||
func _load_main_menu() -> void:
|
||||
SceneLoader.load_scene(main_menu_scene)
|
||||
|
||||
func _advance_level() -> bool:
|
||||
if is_on_last_level(): return false
|
||||
current_level_id += 1
|
||||
return true
|
||||
|
||||
func _advance_and_load_main_menu() -> void:
|
||||
_advance_level()
|
||||
_load_main_menu()
|
||||
|
||||
func _load_ending() -> void:
|
||||
if ending_scene:
|
||||
SceneLoader.load_scene(ending_scene)
|
||||
else:
|
||||
_load_main_menu()
|
||||
|
||||
func _on_level_lost() -> void:
|
||||
if level_lost_scene:
|
||||
var instance = level_lost_scene.instantiate()
|
||||
get_tree().current_scene.add_child(instance)
|
||||
_try_connecting_signal_to_node(instance, &"restart_pressed", _reload_level)
|
||||
_try_connecting_signal_to_node(instance, &"main_menu_pressed", _load_main_menu)
|
||||
else:
|
||||
_reload_level()
|
||||
|
||||
func get_current_level_id() -> int:
|
||||
return current_level_id if force_level == -1 else force_level
|
||||
|
||||
func load_current_level() -> void:
|
||||
level_list_loader.load_level(get_current_level_id())
|
||||
|
||||
func _advance_and_reload() -> void:
|
||||
var _prior_level_id = get_current_level_id()
|
||||
_advance_level()
|
||||
current_level_id = _prior_level_id
|
||||
load_current_level()
|
||||
|
||||
func _load_next_level() -> void:
|
||||
_advance_level()
|
||||
load_current_level()
|
||||
|
||||
func _reload_level() -> void:
|
||||
load_current_level()
|
||||
|
||||
func _load_win_screen_or_ending() -> void:
|
||||
if game_won_scene:
|
||||
var instance = game_won_scene.instantiate()
|
||||
get_tree().current_scene.add_child(instance)
|
||||
_try_connecting_signal_to_node(instance, &"continue_pressed", _load_ending)
|
||||
_try_connecting_signal_to_node(instance, &"restart_pressed", _reload_level)
|
||||
_try_connecting_signal_to_node(instance, &"main_menu_pressed", _load_main_menu)
|
||||
else:
|
||||
_load_ending()
|
||||
|
||||
func _load_level_complete_screen_or_next_level() -> void:
|
||||
if level_won_scene:
|
||||
var instance = level_won_scene.instantiate()
|
||||
get_tree().current_scene.add_child(instance)
|
||||
_try_connecting_signal_to_node(instance, &"continue_pressed", _load_next_level)
|
||||
_try_connecting_signal_to_node(instance, &"restart_pressed", _advance_and_reload)
|
||||
_try_connecting_signal_to_node(instance, &"main_menu_pressed", _advance_and_load_main_menu)
|
||||
else:
|
||||
_load_next_level()
|
||||
|
||||
func is_on_last_level() -> bool:
|
||||
return get_current_level_id() + 1 >= level_list_loader.files.size()
|
||||
|
||||
func _on_level_won():
|
||||
if is_on_last_level():
|
||||
_load_win_screen_or_ending()
|
||||
else:
|
||||
_load_level_complete_screen_or_next_level()
|
||||
|
||||
func _connect_level_signals() -> void:
|
||||
_try_connecting_signal_to_level(&"level_won", _on_level_won)
|
||||
_try_connecting_signal_to_level(&"level_lost", _on_level_lost)
|
||||
_try_connecting_signal_to_level(&"level_skipped", _load_next_level)
|
||||
|
||||
func _on_level_loader_level_loaded() -> void:
|
||||
current_level = level_list_loader.current_level
|
||||
await current_level.ready
|
||||
_connect_level_signals()
|
||||
if level_loading_screen:
|
||||
level_loading_screen.close()
|
||||
|
||||
func _on_level_loader_levels_finished() -> void:
|
||||
_load_win_screen_or_ending()
|
||||
|
||||
func _on_level_loader_level_load_started() -> void:
|
||||
if level_loading_screen:
|
||||
level_loading_screen.reset()
|
||||
|
||||
func _ready() -> void:
|
||||
level_list_loader.level_loaded.connect(_on_level_loader_level_loaded)
|
||||
level_list_loader.levels_finished.connect(_on_level_loader_levels_finished)
|
||||
level_list_loader.level_load_started.connect(_on_level_loader_level_load_started)
|
||||
if auto_load:
|
||||
load_current_level()
|
@ -0,0 +1 @@
|
||||
uid://yakisxcmflgk
|
52
addons/maaacks_game_template/extras/scripts/level_loader.gd
Normal file
52
addons/maaacks_game_template/extras/scripts/level_loader.gd
Normal file
@ -0,0 +1,52 @@
|
||||
@tool
|
||||
class_name LevelLoader
|
||||
extends Node
|
||||
## Loads scenes into a container.
|
||||
|
||||
signal level_load_started
|
||||
signal level_loaded
|
||||
signal level_ready
|
||||
|
||||
## Container where the level instance will be added.
|
||||
@export var level_container : Node
|
||||
## Loads a level on start.
|
||||
@export var auto_load : bool = false
|
||||
@export var current_level_path : String
|
||||
@export_group("Debugging")
|
||||
@export var force_level : String
|
||||
@export var current_level : Node
|
||||
|
||||
var is_loading : bool = false
|
||||
|
||||
func get_current_level_path() -> String:
|
||||
return current_level_path if force_level.is_empty() else force_level
|
||||
|
||||
func _attach_level(level_resource : Resource):
|
||||
assert(level_container != null, "level_container is null")
|
||||
var instance = level_resource.instantiate()
|
||||
level_container.call_deferred("add_child", instance)
|
||||
return instance
|
||||
|
||||
func load_level(level_path : String = get_current_level_path()):
|
||||
if is_loading : return
|
||||
if is_instance_valid(current_level):
|
||||
current_level.queue_free()
|
||||
await current_level.tree_exited
|
||||
current_level = null
|
||||
is_loading = true
|
||||
current_level_path = level_path
|
||||
SceneLoader.load_scene(level_path, true)
|
||||
level_load_started.emit()
|
||||
await SceneLoader.scene_loaded
|
||||
is_loading = false
|
||||
current_level = _attach_level(SceneLoader.get_resource())
|
||||
level_loaded.emit()
|
||||
await current_level.ready
|
||||
level_ready.emit()
|
||||
|
||||
func reload_level():
|
||||
load_level()
|
||||
|
||||
func _ready():
|
||||
if auto_load:
|
||||
load_level()
|
@ -0,0 +1 @@
|
||||
uid://bbymrin0cm704
|
23
addons/maaacks_game_template/extras/scripts/scene_lister.gd
Normal file
23
addons/maaacks_game_template/extras/scripts/scene_lister.gd
Normal file
@ -0,0 +1,23 @@
|
||||
@tool
|
||||
extends Node
|
||||
class_name SceneLister
|
||||
## Helper class for listing all the scenes in a directory.
|
||||
|
||||
## List of paths to scene files.
|
||||
## Prefilled in the editor by selecting a directory.
|
||||
@export var files : Array[String]
|
||||
## Prefill files with any scenes in the directory.
|
||||
@export_dir var directory : String :
|
||||
set(value):
|
||||
directory = value
|
||||
_refresh_files()
|
||||
|
||||
func _refresh_files():
|
||||
if not is_inside_tree() or directory.is_empty(): return
|
||||
var dir_access = DirAccess.open(directory)
|
||||
if dir_access:
|
||||
files.clear()
|
||||
for file in dir_access.get_files():
|
||||
if not file.ends_with(".tscn"):
|
||||
continue
|
||||
files.append(directory + "/" + file)
|
@ -0,0 +1 @@
|
||||
uid://wjq7li836lwj
|
Reference in New Issue
Block a user