Sweet title screen!

This commit is contained in:
Rob Kelly 2025-04-22 21:30:11 -06:00
parent 9747e80f1d
commit bc9e928c3b
13 changed files with 882 additions and 24 deletions

BIN
asset_dev/ui/title.xcf Normal file

Binary file not shown.

BIN
assets/ui/title.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://buc0oy5col0et"
path="res://.godot/imported/title.png-534804d7bf6a63fbbb0c46e68d8e4660.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/ui/title.png"
dest_files=["res://.godot/imported/title.png-534804d7bf6a63fbbb0c46e68d8e4660.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

View File

@ -41,7 +41,6 @@ gdscript/warnings/unsafe_call_argument=2
window/size/viewport_width=1920
window/size/viewport_height=1080
window/stretch/mode="canvas_items"
[dotnet]

View File

@ -85,6 +85,8 @@ func _finish_scene_load(scene_instance: Node) -> void:
# Reset time scale in case it's been changed.
Engine.time_scale = 1.0
_unload_content()
content.add_child(scene_instance)
scene_instance.reparent(content)

View File

@ -160,7 +160,7 @@ transitions = ["Start", "initial_display", SubResource("AnimationNodeStateMachin
[node name="Game" type="Node"]
script = ExtResource("1_qnjlk")
start_scene = "uid://884jqafhtrv0"
start_scene = "uid://bctwol681jdk0"
[node name="Content" type="Node" parent="."]
unique_name_in_owner = true

View File

@ -0,0 +1,40 @@
extends Control
## Title screen!
@export_category("Game Scenes")
# TODO is there a way to get the appropriate level scene path here without loading the world scene?
@export_file("*.tscn") var level_scene: String
@export_file("*.tscn") var world_scene: String
@export var settings_scene: PackedScene
@onready var continue_button: Button = %Continue
@onready var settings_container: Control = %SettingsContainer
func _ready() -> void:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
var save_path := _get_save_path()
if FileAccess.file_exists(save_path):
continue_button.disabled = false
func _get_save_path() -> String:
return World.get_save_path(level_scene)
func continue_game() -> void:
LoadingTools.load_save(_get_save_path())
func new_game() -> void:
LoadingTools.load_level(level_scene)
func show_settings() -> void:
var instance: Control = settings_scene.instantiate()
settings_container.add_child(instance)
func quit() -> void:
get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST)

View File

@ -0,0 +1 @@
uid://dysldhadfr4oj

Binary file not shown.

View File

@ -0,0 +1,756 @@
[gd_scene load_steps=18 format=3 uid="uid://bctwol681jdk0"]
[ext_resource type="Theme" uid="uid://dj2ij1b2yjicr" path="res://src/ui/menus/title_screen/title_screen.theme" id="1_3lcvc"]
[ext_resource type="PackedScene" uid="uid://b6dx0ovy15g5o" path="res://src/effects/grunk_2d/grunk_2d.tscn" id="2_7vchy"]
[ext_resource type="Script" uid="uid://dysldhadfr4oj" path="res://src/ui/menus/title_screen/title_screen.gd" id="2_rjwhj"]
[ext_resource type="Texture2D" uid="uid://buc0oy5col0et" path="res://assets/ui/title.png" id="2_uxv0r"]
[ext_resource type="PackedScene" uid="uid://d3eaqw2rdurct" path="res://src/ui/menus/settings_menu/settings_menu.tscn" id="3_wqn52"]
[ext_resource type="Shader" uid="uid://dnytoirugot2e" path="res://src/shaders/canvas_grunk.gdshader" id="3_yrys0"]
[ext_resource type="FastNoiseLite" uid="uid://cnlvdtx68giv6" path="res://assets/materials/gunk_noise.tres" id="4_cgiy0"]
[ext_resource type="Texture2D" uid="uid://dixpjnlaj86x2" path="res://assets/ui/corpo_logo/corpo_logo_128.png" id="5_yrys0"]
[ext_resource type="FontFile" uid="uid://bgy7odoob7xyl" path="res://assets/fonts/Silkscreen/Silkscreen-Bold.ttf" id="6_cgiy0"]
[sub_resource type="NoiseTexture3D" id="NoiseTexture3D_7v5ka"]
width = 256
height = 256
seamless = true
seamless_blend_skirt = 0.5
noise = ExtResource("4_cgiy0")
[sub_resource type="NoiseTexture3D" id="NoiseTexture3D_d72jk"]
width = 256
height = 256
seamless = true
seamless_blend_skirt = 0.5
noise = ExtResource("4_cgiy0")
[sub_resource type="FastNoiseLite" id="FastNoiseLite_qsvii"]
frequency = 0.0006
fractal_type = 2
fractal_octaves = 4
fractal_gain = 0.667
domain_warp_type = 2
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_pgbvb"]
width = 1024
height = 1024
noise = SubResource("FastNoiseLite_qsvii")
[sub_resource type="ShaderMaterial" id="ShaderMaterial_rjwhj"]
resource_local_to_scene = true
shader = ExtResource("3_yrys0")
shader_parameter/color_1 = Color(0, 0.03, 0.1, 1)
shader_parameter/color_2 = Color(0, 0.1, 0.3, 1)
shader_parameter/emission_color = Color(0.25, 0.88, 1, 1)
shader_parameter/pixellation = 30.0
shader_parameter/time_pixellation = 30.0
shader_parameter/emission_strength = 0.0
shader_parameter/aspect_ratio = 0.5625
shader_parameter/time_scale = 0.4
shader_parameter/gunk_noise = SubResource("NoiseTexture3D_7v5ka")
shader_parameter/gunk_normal_map = SubResource("NoiseTexture3D_d72jk")
shader_parameter/mask_progress = 0.0
shader_parameter/mask_noise = SubResource("NoiseTexture2D_pgbvb")
[sub_resource type="Animation" id="Animation_uxv0r"]
resource_name = "display"
length = 10.0
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("VBoxContainer/Loader/Done:visible_ratio")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0.0, 1.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("VBoxContainer/TitleContainer:custom_minimum_size")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 6.15, 6.2, 6.25, 6.3, 6.35, 6.4, 6.45, 6.5, 6.55, 6.6, 6.65),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [Vector2(1024, 0), Vector2(1024, 48), Vector2(1024, 96), Vector2(1024, 144), Vector2(1024, 192), Vector2(1024, 240), Vector2(1024, 288), Vector2(1024, 336), Vector2(1024, 384), Vector2(1024, 432), Vector2(1024, 480), Vector2(1024, 528)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("VBoxContainer/WarningMessage/LogoContainer:custom_minimum_size")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 1, 1.1, 1.2, 1.3),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
"update": 1,
"values": [Vector2(128, 0), Vector2(128, 32), Vector2(128, 64), Vector2(128, 96), Vector2(128, 128)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Warning:visible_ratio")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0, 1.35, 1.45),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [0.0, 0.0, 1.0]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Warning2:visible_ratio")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0, 2.35, 2.75),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [0.0, 0.0, 1.0]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2/Warning3:visible_ratio")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0, 3.65, 4.15),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [0.0, 0.0, 1.0]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Blinker:visible")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0, 1.45, 1.6, 1.75139, 1.9, 2.05139, 2.2, 2.35, 2.75, 2.90139, 3.05, 3.20139, 3.35, 3.5, 3.65),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [false, true, false, true, false, true, false, true, false, true, false, true, false, true, false]
}
tracks/7/type = "value"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2/Blinker2:visible")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0, 4.15, 4.3, 4.45139, 4.6, 4.75139, 4.9, 5.05, 5.2, 5.35139, 5.5, 5.65, 5.79861, 5.95, 6.09861),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [false, true, false, true, false, true, false, true, false, true, false, true, false, true, false]
}
tracks/8/type = "value"
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1:visible")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/keys = {
"times": PackedFloat32Array(0, 1.3),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, true]
}
tracks/9/type = "value"
tracks/9/imported = false
tracks/9/enabled = true
tracks/9/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2:visible")
tracks/9/interp = 1
tracks/9/loop_wrap = true
tracks/9/keys = {
"times": PackedFloat32Array(0, 3.65),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, true]
}
tracks/10/type = "value"
tracks/10/imported = false
tracks/10/enabled = true
tracks/10/path = NodePath("VBoxContainer/BufferSpace:custom_minimum_size")
tracks/10/interp = 1
tracks/10/loop_wrap = true
tracks/10/keys = {
"times": PackedFloat32Array(0, 7.75, 7.8, 7.85, 7.9, 7.95, 8, 8.05, 8.1, 8.15, 8.2, 8.25, 8.3, 8.35, 8.4, 8.45, 8.5, 8.55, 8.6, 8.65, 8.7, 8.75, 8.8, 8.85),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [Vector2(1024, 0), Vector2(1024, 48), Vector2(1024, 96), Vector2(1024, 144), Vector2(1024, 192), Vector2(1024, 240), Vector2(1024, 288), Vector2(1024, 336), Vector2(1024, 384), Vector2(1024, 432), Vector2(1024, 480), Vector2(1024, 528), Vector2(1024, 576), Vector2(1024, 624), Vector2(1024, 672), Vector2(1024, 720), Vector2(1024, 768), Vector2(1024, 816), Vector2(1024, 864), Vector2(1024, 912), Vector2(1024, 960), Vector2(1024, 1008), Vector2(1024, 1056), Vector2(1024, 1104)]
}
tracks/11/type = "value"
tracks/11/imported = false
tracks/11/enabled = true
tracks/11/path = NodePath("../Grunk2D:material:shader_parameter/mask_progress")
tracks/11/interp = 1
tracks/11/loop_wrap = true
tracks/11/keys = {
"times": PackedFloat32Array(0, 6.15, 10),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [0.0, 0.0, 1.0]
}
tracks/12/type = "value"
tracks/12/imported = false
tracks/12/enabled = true
tracks/12/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Continue:visible")
tracks/12/interp = 1
tracks/12/loop_wrap = true
tracks/12/keys = {
"times": PackedFloat32Array(0, 6.75),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, true]
}
tracks/13/type = "value"
tracks/13/imported = false
tracks/13/enabled = true
tracks/13/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/NewGame:visible")
tracks/13/interp = 1
tracks/13/loop_wrap = true
tracks/13/keys = {
"times": PackedFloat32Array(0, 7),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, true]
}
tracks/14/type = "value"
tracks/14/imported = false
tracks/14/enabled = true
tracks/14/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Settings:visible")
tracks/14/interp = 1
tracks/14/loop_wrap = true
tracks/14/keys = {
"times": PackedFloat32Array(0, 7.25),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, true]
}
tracks/15/type = "value"
tracks/15/imported = false
tracks/15/enabled = true
tracks/15/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Quit:visible")
tracks/15/interp = 1
tracks/15/loop_wrap = true
tracks/15/keys = {
"times": PackedFloat32Array(0, 7.5),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, true]
}
tracks/16/type = "value"
tracks/16/imported = false
tracks/16/enabled = true
tracks/16/path = NodePath("VBoxContainer/MarginContainer:visible")
tracks/16/interp = 1
tracks/16/loop_wrap = true
tracks/16/keys = {
"times": PackedFloat32Array(0, 6.75),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, true]
}
tracks/17/type = "value"
tracks/17/imported = false
tracks/17/enabled = true
tracks/17/path = NodePath("VBoxContainer/TitleContainer:visible")
tracks/17/interp = 1
tracks/17/loop_wrap = true
tracks/17/keys = {
"times": PackedFloat32Array(0, 6.15),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, true]
}
tracks/18/type = "value"
tracks/18/imported = false
tracks/18/enabled = true
tracks/18/path = NodePath("VBoxContainer/BufferSpace:visible")
tracks/18/interp = 1
tracks/18/loop_wrap = true
tracks/18/keys = {
"times": PackedFloat32Array(0, 7.75),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, true]
}
tracks/19/type = "value"
tracks/19/imported = false
tracks/19/enabled = true
tracks/19/path = NodePath("VBoxContainer/WarningMessage:visible")
tracks/19/interp = 1
tracks/19/loop_wrap = true
tracks/19/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, true]
}
[sub_resource type="Animation" id="Animation_iv5x5"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("VBoxContainer/Loader/Done:visible_ratio")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("VBoxContainer/TitleContainer:custom_minimum_size")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(800, 0)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("VBoxContainer/WarningMessage/LogoContainer:custom_minimum_size")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(128, 0)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Warning:visible_ratio")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Warning2:visible_ratio")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2/Warning3:visible_ratio")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1/Blinker:visible")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/7/type = "value"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2/Blinker2:visible")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/8/type = "value"
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line1:visible")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/9/type = "value"
tracks/9/imported = false
tracks/9/enabled = true
tracks/9/path = NodePath("VBoxContainer/WarningMessage/VBoxContainer/Line2:visible")
tracks/9/interp = 1
tracks/9/loop_wrap = true
tracks/9/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/10/type = "value"
tracks/10/imported = false
tracks/10/enabled = true
tracks/10/path = NodePath("VBoxContainer/BufferSpace:custom_minimum_size")
tracks/10/interp = 1
tracks/10/loop_wrap = true
tracks/10/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(1024, 0)]
}
tracks/11/type = "value"
tracks/11/imported = false
tracks/11/enabled = true
tracks/11/path = NodePath("../Grunk2D:material:shader_parameter/mask_progress")
tracks/11/interp = 1
tracks/11/loop_wrap = true
tracks/11/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/12/type = "value"
tracks/12/imported = false
tracks/12/enabled = true
tracks/12/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Continue:visible")
tracks/12/interp = 1
tracks/12/loop_wrap = true
tracks/12/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/13/type = "value"
tracks/13/imported = false
tracks/13/enabled = true
tracks/13/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/NewGame:visible")
tracks/13/interp = 1
tracks/13/loop_wrap = true
tracks/13/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/14/type = "value"
tracks/14/imported = false
tracks/14/enabled = true
tracks/14/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Settings:visible")
tracks/14/interp = 1
tracks/14/loop_wrap = true
tracks/14/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/15/type = "value"
tracks/15/imported = false
tracks/15/enabled = true
tracks/15/path = NodePath("VBoxContainer/MarginContainer/MenuButtons/Quit:visible")
tracks/15/interp = 1
tracks/15/loop_wrap = true
tracks/15/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/16/type = "value"
tracks/16/imported = false
tracks/16/enabled = true
tracks/16/path = NodePath("VBoxContainer/MarginContainer:visible")
tracks/16/interp = 1
tracks/16/loop_wrap = true
tracks/16/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/17/type = "value"
tracks/17/imported = false
tracks/17/enabled = true
tracks/17/path = NodePath("VBoxContainer/TitleContainer:visible")
tracks/17/interp = 1
tracks/17/loop_wrap = true
tracks/17/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/18/type = "value"
tracks/18/imported = false
tracks/18/enabled = true
tracks/18/path = NodePath("VBoxContainer/BufferSpace:visible")
tracks/18/interp = 1
tracks/18/loop_wrap = true
tracks/18/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/19/type = "value"
tracks/19/imported = false
tracks/19/enabled = true
tracks/19/path = NodePath("VBoxContainer/WarningMessage:visible")
tracks/19/interp = 1
tracks/19/loop_wrap = true
tracks/19/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_3qdtd"]
_data = {
&"RESET": SubResource("Animation_iv5x5"),
&"display": SubResource("Animation_uxv0r")
}
[node name="TitleScreen" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme = ExtResource("1_3lcvc")
script = ExtResource("2_rjwhj")
level_scene = "uid://bov4ok76woyc"
world_scene = "uid://884jqafhtrv0"
settings_scene = ExtResource("3_wqn52")
[node name="ColorRect" type="ColorRect" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0.0196078, 0.0431373, 0.0627451, 1)
[node name="Grunk2D" parent="." instance=ExtResource("2_7vchy")]
material = SubResource("ShaderMaterial_rjwhj")
layout_mode = 1
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 1
anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_top = -73.0
offset_right = 440.0
grow_vertical = 0
theme_override_constants/margin_left = 32
theme_override_constants/margin_bottom = 32
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 32
[node name="Loader" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="Prompt" type="Label" parent="MarginContainer/VBoxContainer/Loader"]
layout_mode = 2
text = ">"
[node name="Loading" type="Label" parent="MarginContainer/VBoxContainer/Loader"]
layout_mode = 2
text = "UI_LOADING"
visible_characters_behavior = 1
[node name="Ellipsis" type="Label" parent="MarginContainer/VBoxContainer/Loader"]
layout_mode = 2
text = "... "
visible_characters_behavior = 1
[node name="Done" type="Label" parent="MarginContainer/VBoxContainer/Loader"]
layout_mode = 2
text = "Done!"
visible_characters = 0
visible_characters_behavior = 1
visible_ratio = 0.0
[node name="WarningMessage" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
visible = false
layout_mode = 2
theme_override_constants/separation = 32
[node name="LogoContainer" type="Control" parent="MarginContainer/VBoxContainer/WarningMessage"]
clip_contents = true
custom_minimum_size = Vector2(128, 0)
layout_mode = 2
size_flags_vertical = 0
[node name="Logo" type="TextureRect" parent="MarginContainer/VBoxContainer/WarningMessage/LogoContainer"]
modulate = Color(0.137255, 0.984314, 0.34902, 1)
layout_mode = 1
offset_right = 128.0
offset_bottom = 128.0
texture = ExtResource("5_yrys0")
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/WarningMessage"]
layout_mode = 2
theme_override_constants/separation = 16
alignment = 2
[node name="Line1" type="HBoxContainer" parent="MarginContainer/VBoxContainer/WarningMessage/VBoxContainer"]
visible = false
layout_mode = 2
[node name="Warning" type="Label" parent="MarginContainer/VBoxContainer/WarningMessage/VBoxContainer/Line1"]
layout_mode = 2
theme_override_fonts/font = ExtResource("6_cgiy0")
text = "!WARNING!"
visible_characters = 0
visible_ratio = 0.0
[node name="Warning2" type="Label" parent="MarginContainer/VBoxContainer/WarningMessage/VBoxContainer/Line1"]
layout_mode = 2
text = " This is a secure terminal system."
visible_characters = 0
visible_ratio = 0.0
[node name="Blinker" type="Label" parent="MarginContainer/VBoxContainer/WarningMessage/VBoxContainer/Line1"]
visible = false
layout_mode = 2
text = "_"
[node name="Line2" type="HBoxContainer" parent="MarginContainer/VBoxContainer/WarningMessage/VBoxContainer"]
visible = false
layout_mode = 2
[node name="Warning3" type="Label" parent="MarginContainer/VBoxContainer/WarningMessage/VBoxContainer/Line2"]
layout_mode = 2
text = "Unauthorized access is prohibited under penalty of"
visible_characters = 0
visible_ratio = 0.0
[node name="Blinker2" type="Label" parent="MarginContainer/VBoxContainer/WarningMessage/VBoxContainer/Line2"]
visible = false
layout_mode = 2
text = "_"
[node name="BufferSpace" type="Control" parent="MarginContainer/VBoxContainer"]
visible = false
custom_minimum_size = Vector2(1024, 0)
layout_mode = 2
[node name="TitleContainer" type="Control" parent="MarginContainer/VBoxContainer"]
visible = false
clip_contents = true
custom_minimum_size = Vector2(800, 0)
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/TitleContainer"]
layout_mode = 1
offset_right = 968.0
offset_bottom = 432.0
theme_override_constants/margin_left = 64
[node name="Title" type="TextureRect" parent="MarginContainer/VBoxContainer/TitleContainer/MarginContainer"]
modulate = Color(0.137255, 0.984314, 0.34902, 1)
texture_filter = 3
layout_mode = 2
texture = ExtResource("2_uxv0r")
stretch_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer"]
visible = false
layout_mode = 2
theme_override_constants/margin_left = 64
[node name="MenuButtons" type="VBoxContainer" parent="MarginContainer/VBoxContainer/MarginContainer"]
custom_minimum_size = Vector2(300, 0)
layout_mode = 2
size_flags_horizontal = 0
theme_override_constants/separation = 32
[node name="Continue" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer/MenuButtons"]
unique_name_in_owner = true
visible = false
layout_mode = 2
disabled = true
text = "Continue"
[node name="NewGame" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer/MenuButtons"]
visible = false
layout_mode = 2
text = "New Game"
[node name="Settings" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer/MenuButtons"]
visible = false
layout_mode = 2
text = "Settings"
[node name="Quit" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer/MenuButtons"]
visible = false
layout_mode = 2
theme_type_variation = &"DangerButton"
text = "Quit"
[node name="AnimationPlayer" type="AnimationPlayer" parent="MarginContainer"]
libraries = {
&"": SubResource("AnimationLibrary_3qdtd")
}
autoplay = "display"
[node name="SettingsContainer" type="Control" parent="."]
unique_name_in_owner = true
custom_minimum_size = Vector2(1000, 600)
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -500.0
offset_right = 500.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
[connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/MenuButtons/Continue" to="." method="continue_game"]
[connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/MenuButtons/NewGame" to="." method="new_game"]
[connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/MenuButtons/Settings" to="." method="show_settings"]
[connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/MenuButtons/Quit" to="." method="quit"]

22
src/util/loading_tools.gd Normal file
View File

@ -0,0 +1,22 @@
class_name LoadingTools
## Utilities for loading game states
const WORLD_SCENE := "res://src/world/world.tscn"
static func _load_world(level: PackedScene, save: SaveState = null) -> void:
var finish_load := func(world: World) -> void:
world.save_state = save
world.initial_level = level
Game.instance.queue_scene(WORLD_SCENE).then(finish_load)
static func load_level(level_path: String, save: SaveState = null) -> void:
var chain_load := func(level: PackedScene) -> void: LoadingTools._load_world(level, save)
Game.instance.queue_load(level_path).then(chain_load)
static func load_save(save_path: String) -> void:
var chain_load := func(save: SaveState) -> void: load_level(save.level_path, save)
Game.instance.queue_load(save_path).then(chain_load)

View File

@ -0,0 +1 @@
uid://b1hmb3efjqldu

View File

@ -1,8 +1,11 @@
class_name World extends Node
## Access and flow control for the game world.
const SAVE_PATH_FMT := "user://{0}.state.res"
@export var pause_enabled := true
@export var save_path_fmt := "user://{0}.state.res"
@export var save_state: SaveState
@export var manager: WorldManager
@export var spook_manager: SpookManager
@ -28,7 +31,8 @@ func _ready() -> void:
manager.alert_raised.connect(spook_manager.on_alert_raised)
manager.alert_cleared.connect(spook_manager.on_alert_cleared)
manager.player_dead.connect(on_player_death)
load_level(initial_level)
if initial_level:
load_level(initial_level)
func _unhandled_input(event: InputEvent) -> void:
@ -47,20 +51,7 @@ func unpause() -> void:
get_tree().paused = false
func _get_level_id(level: PackedScene) -> String:
if level.resource_path:
var file := level.resource_path.get_file()
if file:
return file
return level.resource_path
return "level"
func _get_save_path(level: PackedScene) -> String:
return save_path_fmt.format([_get_level_id(level)])
func load_level(level: PackedScene, save: SaveState = null) -> void:
func load_level(level: PackedScene) -> void:
for c: Node in level_root.get_children():
c.queue_free()
level_root.remove_child(c)
@ -68,8 +59,8 @@ func load_level(level: PackedScene, save: SaveState = null) -> void:
print("Instantiating level from ", level.resource_path)
var level_instance := level.instantiate()
level_root.add_child(level_instance)
if save:
save.load_to_world(self)
if save_state:
save_state.load_to_world(self)
print("Done!")
spook_manager.after_level_init()
@ -81,13 +72,14 @@ func on_player_death() -> void:
func _reload_saved(save: SaveState) -> void:
load_level(current_level, save)
save_state = save
load_level(current_level)
func on_game_over() -> void:
# reload the level from the last save
var save_path := _get_save_path(current_level)
if ResourceLoader.exists(save_path):
var save_path := World.get_level_save_path(current_level)
if FileAccess.file_exists(save_path):
Game.instance.queue_load(save_path).finally(_reload_saved)
else:
load_level(current_level)
@ -97,8 +89,16 @@ func save_progress() -> void:
print("Preparing save state...")
save_icon.show()
var save := SaveState.serialize(self)
var save_path := _get_save_path(current_level)
var save_path := World.get_level_save_path(current_level)
print("Writing save to ", save_path)
ResourceSaver.save(save, save_path)
save_icon.hide()
print("Done!")
static func get_save_path(level_path: String) -> String:
return SAVE_PATH_FMT.format([level_path.get_basename().get_file()])
static func get_level_save_path(level: PackedScene) -> String:
return World.get_save_path(level.resource_path)