diff --git a/asset_dev/ui/title.xcf b/asset_dev/ui/title.xcf new file mode 100644 index 0000000..0bc0286 Binary files /dev/null and b/asset_dev/ui/title.xcf differ diff --git a/assets/ui/title.png b/assets/ui/title.png new file mode 100644 index 0000000..1fe6590 --- /dev/null +++ b/assets/ui/title.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60cd1908e6fbdf743ae007e6066aafb3955ee9e2764f23ee53f4a5284f0164b0 +size 7130 diff --git a/assets/ui/title.png.import b/assets/ui/title.png.import new file mode 100644 index 0000000..425d941 --- /dev/null +++ b/assets/ui/title.png.import @@ -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 diff --git a/project.godot b/project.godot index 1558793..deee298 100644 --- a/project.godot +++ b/project.godot @@ -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] diff --git a/src/game/game.gd b/src/game/game.gd index 35c3f2b..3bfbe0b 100644 --- a/src/game/game.gd +++ b/src/game/game.gd @@ -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) diff --git a/src/game/game.tscn b/src/game/game.tscn index d17cb34..eaa4032 100644 --- a/src/game/game.tscn +++ b/src/game/game.tscn @@ -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 diff --git a/src/ui/menus/title_screen/title_screen.gd b/src/ui/menus/title_screen/title_screen.gd new file mode 100644 index 0000000..3eacfc8 --- /dev/null +++ b/src/ui/menus/title_screen/title_screen.gd @@ -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) diff --git a/src/ui/menus/title_screen/title_screen.gd.uid b/src/ui/menus/title_screen/title_screen.gd.uid new file mode 100644 index 0000000..06107cc --- /dev/null +++ b/src/ui/menus/title_screen/title_screen.gd.uid @@ -0,0 +1 @@ +uid://dysldhadfr4oj diff --git a/src/ui/menus/title_screen/title_screen.theme b/src/ui/menus/title_screen/title_screen.theme new file mode 100644 index 0000000..db6979c Binary files /dev/null and b/src/ui/menus/title_screen/title_screen.theme differ diff --git a/src/ui/menus/title_screen/title_screen.tscn b/src/ui/menus/title_screen/title_screen.tscn new file mode 100644 index 0000000..db8ff73 --- /dev/null +++ b/src/ui/menus/title_screen/title_screen.tscn @@ -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"] diff --git a/src/util/loading_tools.gd b/src/util/loading_tools.gd new file mode 100644 index 0000000..91a4ebc --- /dev/null +++ b/src/util/loading_tools.gd @@ -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) diff --git a/src/util/loading_tools.gd.uid b/src/util/loading_tools.gd.uid new file mode 100644 index 0000000..7fb5b99 --- /dev/null +++ b/src/util/loading_tools.gd.uid @@ -0,0 +1 @@ +uid://b1hmb3efjqldu diff --git a/src/world/world.gd b/src/world/world.gd index 2d10452..e002db9 100644 --- a/src/world/world.gd +++ b/src/world/world.gd @@ -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)