saving for player and savespots implemented

This commit is contained in:
Rakarake 2025-07-06 17:37:26 +02:00
parent 8a564ec252
commit 924d2f3772
10 changed files with 75 additions and 15 deletions

View file

@ -16,6 +16,8 @@ now 327 years in the making!
* F5 to respawn * F5 to respawn
* F6 to set respawn point (remembers across sessions) * F6 to set respawn point (remembers across sessions)
* C to toggle debug camera, left-click then drag to pan * C to toggle debug camera, left-click then drag to pan
* Ctlr-S to save game.
* Ctlr-O to load game.
> [!IMPORTANT] > [!IMPORTANT]
> This repo uses git LFS. > This repo uses git LFS.

View file

@ -149,8 +149,21 @@ func _ready():
fade(true, 0) fade(true, 0)
if !enter_scene(): if !enter_scene():
fade(false) fade(false)
# Load/set save stuff
print(Global.save.get("player")) ## Called node should save it's properties. Might not acutally be saving
## the game.
func on_game_saved():
if !Global.save.has("player"):
Global.save["player"] = {}
for a in saved_attributes:
Global.save["player"][a] = self[a]
## Called when game is loaded.
func on_game_loaded():
if Global.save.has("player"):
for a in saved_attributes:
if Global.save["player"].has(a):
self[a] = Global.save["player"][a]
func update_looking_right(): func update_looking_right():
if input_dir.x < 0: if input_dir.x < 0:

View file

@ -3009,11 +3009,12 @@ size = Vector2(122.5, 289.167)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_wvy82"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_wvy82"]
size = Vector2(117.026, 281.85) size = Vector2(117.026, 281.85)
[node name="Player" type="CharacterBody2D" groups=["cross_scene", "debug_trail", "player"]] [node name="Player" type="CharacterBody2D" groups=["cross_scene", "debug_trail", "player", "saved"]]
light_mask = 0 light_mask = 0
visibility_layer = 4 visibility_layer = 4
collision_layer = 4 collision_layer = 4
script = ExtResource("1_l3wc5") script = ExtResource("1_l3wc5")
saved_attributes = Array[String](["double_jump_enabled", "dash_enabled", "wavedash_enabled", "wallslide_enabled", "dashjump_enabled"])
buffer_jump = 0.15 buffer_jump = 0.15
coyote_jump = 0.05 coyote_jump = 0.05
double_jump_delay = 0.05 double_jump_delay = 0.05

View file

@ -32,6 +32,8 @@ const LOG_COLOR_START := Color(1,1,1,0.3)
const LOG_COLOR_END := Color(0.2,0.2,0.9,0.3) const LOG_COLOR_END := Color(0.2,0.2,0.9,0.3)
var _log_color_progress := 0.0 var _log_color_progress := 0.0
var _log_color_reversing := false var _log_color_reversing := false
## Expects dictionary with keys "description" and "text".
func put_log(value: Dictionary): func put_log(value: Dictionary):
if control_root.visible: if control_root.visible:
var new_label = default_label.instantiate() var new_label = default_label.instantiate()
@ -109,13 +111,6 @@ func maybe_put_stat(stat_key, value: String):
stat_key["value"] = value stat_key["value"] = value
stat_set(stat_key) stat_set(stat_key)
func _process(delta: float):
# Save/load game with keyboard shortcuts
if Input.is_action_just_pressed("debug_save_game"):
Global.save_game()
if Input.is_action_just_pressed("debug_load_game"):
Global.load_game()
func _physics_process(_delta): func _physics_process(_delta):
if Input.is_action_just_pressed("show_stats"): if Input.is_action_just_pressed("show_stats"):
control_root.visible = !control_root.visible control_root.visible = !control_root.visible
@ -147,6 +142,14 @@ func _physics_process(_delta):
process_debug_property("debug_trail", process_debug_property("debug_trail",
func(): return preload("res://debug/Trail.tscn").instantiate(), func(_item): ) func(): return preload("res://debug/Trail.tscn").instantiate(), func(_item): )
# Save/load game with keyboard shortcuts
if Input.is_action_just_pressed("debug_save_game"):
Global.notify_save()
Global.save_game()
if Input.is_action_just_pressed("debug_load_game"):
Global.notify_load()
Global.load_game()
func process_debug_property(debug_name, create_func, process_func): func process_debug_property(debug_name, create_func, process_func):
for node in get_tree().get_nodes_in_group(debug_name): for node in get_tree().get_nodes_in_group(debug_name):
var item var item

View file

@ -44,7 +44,7 @@ func _process(_delta):
DisplayServer.window_set_mode(new_mode) DisplayServer.window_set_mode(new_mode)
if Input.is_action_just_pressed("pause") || (paused && Input.is_action_just_pressed("ui_cancel")): if Input.is_action_just_pressed("pause") || (paused && Input.is_action_just_pressed("ui_cancel")):
toggle_pause() toggle_pause()
Debug.stat_set({"key": "current save", "value": save_name}) Debug.stat_set({"key": "save file", "value": save_name})
## Saves settings specifically, no game save. Can be used by outside stuff for ## Saves settings specifically, no game save. Can be used by outside stuff for
## debug e.g. ## debug e.g.
@ -78,6 +78,19 @@ func load_game():
else: else:
save = s save = s
## Notify everything in the scene tree to save their stuff. Hopefully we could
## make this async.
func notify_save():
Debug.put_log({"description": "save", "text": "notifying save"})
for n in get_tree().get_nodes_in_group("saved"):
n.on_game_saved()
## Notify everything in the scene tree to save their stuff.
func notify_load():
Debug.put_log({"description": "save", "text": "notifying load"})
for n in get_tree().get_nodes_in_group("saved"):
n.on_game_loaded()
func load_dict(path: String): func load_dict(path: String):
if FileAccess.file_exists(path): if FileAccess.file_exists(path):
var settings_file = FileAccess.open(path, FileAccess.READ) var settings_file = FileAccess.open(path, FileAccess.READ)
@ -124,4 +137,3 @@ func _notification(what):
if what == NOTIFICATION_WM_CLOSE_REQUEST: if what == NOTIFICATION_WM_CLOSE_REQUEST:
print('by by') print('by by')
get_tree().quit() get_tree().quit()

View file

@ -9,4 +9,6 @@ func interact(n):
n.save_animation() n.save_animation()
n.velocity = Vector2.ZERO n.velocity = Vector2.ZERO
n.global_position = global_position n.global_position = global_position
Global.notify_save()
Global.save_game()
saved.emit() saved.emit()

View file

@ -1,8 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://bkh0o0gbpctui"] [gd_scene load_steps=2 format=3 uid="uid://bkh0o0gbpctui"]
[ext_resource type="Script" uid="uid://c6yf4fmct8sfd" path="res://global/powerups/Powerup.gd" id="1_k5ibk"] [ext_resource type="Script" uid="uid://bag8mx58hsiog" path="res://global/saving/SaveSpot.gd" id="1_k5ibk"]
[node name="Powerup" type="Area2D"] [node name="SaveSpot" type="Area2D"]
collision_layer = 256 collision_layer = 256
collision_mask = 0 collision_mask = 0
script = ExtResource("1_k5ibk") script = ExtResource("1_k5ibk")

View file

@ -36,6 +36,8 @@ func transition(n):
if scene != "" && init_grace_tmp < 0: if scene != "" && init_grace_tmp < 0:
n.exit_point = exit_point n.exit_point = exit_point
n.fade(true, enter_time) n.fade(true, enter_time)
# Save everything in scne before exiting, hopefully done asynchronously
Global.notify_save()
await make_walk(n, enter_right, enter_time) await make_walk(n, enter_right, enter_time)
get_tree().change_scene_to_file.call_deferred(scene) get_tree().change_scene_to_file.call_deferred(scene)
@ -58,6 +60,7 @@ func exit_here(n):
# Make actor enter loose control and walk for walk_time seconds # Make actor enter loose control and walk for walk_time seconds
if exit_time != 0: if exit_time != 0:
make_walk(n, !enter_right, exit_time) make_walk(n, !enter_right, exit_time)
Global.notify_load()
await get_tree().create_timer(0.2).timeout await get_tree().create_timer(0.2).timeout
n.fade(false, exit_time) n.fade(false, exit_time)
if snap_to_floor: if snap_to_floor:

View file

@ -56,6 +56,7 @@ cross_scene="Nodes that cross scenes between entry-points"
scene_transition="" scene_transition=""
affectable_camera="a camera that doesn't just contain data for other cameras, wants to be affected by scene transtions etc" affectable_camera="a camera that doesn't just contain data for other cameras, wants to be affected by scene transtions etc"
player="" player=""
saved="save system calls on_game_saved and on_game_load on these nodes"
[importer_defaults] [importer_defaults]

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=17 format=4 uid="uid://bepys2yg3mlfh"] [gd_scene load_steps=19 format=4 uid="uid://bepys2yg3mlfh"]
[ext_resource type="Texture2D" uid="uid://b1ctnt3wnsgj4" path="res://icon.svg" id="1_r51fb"] [ext_resource type="Texture2D" uid="uid://b1ctnt3wnsgj4" path="res://icon.svg" id="1_r51fb"]
[ext_resource type="Script" uid="uid://ddk7mcwdblbf" path="res://global/camera/SceneCamera.gd" id="2_7hrj7"] [ext_resource type="Script" uid="uid://ddk7mcwdblbf" path="res://global/camera/SceneCamera.gd" id="2_7hrj7"]
@ -9,6 +9,7 @@
[ext_resource type="Texture2D" uid="uid://tfth34htn52n" path="res://expressive_stone.png" id="6_3t7se"] [ext_resource type="Texture2D" uid="uid://tfth34htn52n" path="res://expressive_stone.png" id="6_3t7se"]
[ext_resource type="PackedScene" uid="uid://sxcxj2sua5ho" path="res://characters/enemies/Bingus/Bingus.tscn" id="8_puapy"] [ext_resource type="PackedScene" uid="uid://sxcxj2sua5ho" path="res://characters/enemies/Bingus/Bingus.tscn" id="8_puapy"]
[ext_resource type="PackedScene" uid="uid://dwg8c17nqiep2" path="res://global/powerups/Powerup.tscn" id="9_r6xmg"] [ext_resource type="PackedScene" uid="uid://dwg8c17nqiep2" path="res://global/powerups/Powerup.tscn" id="9_r6xmg"]
[ext_resource type="PackedScene" uid="uid://bkh0o0gbpctui" path="res://global/saving/SaveSpot.tscn" id="10_tdtq1"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_6n8gr"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_6n8gr"]
size = Vector2(53.5, 389) size = Vector2(53.5, 389)
@ -40,6 +41,9 @@ size = Vector2(105.5, 1091.25)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_tdtq1"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_tdtq1"]
size = Vector2(216, 208) size = Vector2(216, 208)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_y1jh6"]
size = Vector2(208, 197)
[node name="TestBadPerformance" type="Node2D"] [node name="TestBadPerformance" type="Node2D"]
editor_description = "No fancy graphics stuff here!" editor_description = "No fancy graphics stuff here!"
@ -104,4 +108,23 @@ powerup_enable_property = "dash_enabled"
[node name="CollisionShape2D" type="CollisionShape2D" parent="Powerup"] [node name="CollisionShape2D" type="CollisionShape2D" parent="Powerup"]
shape = SubResource("RectangleShape2D_tdtq1") shape = SubResource("RectangleShape2D_tdtq1")
[node name="Label" type="Label" parent="Powerup"]
offset_left = -86.0
offset_top = -75.0
offset_right = 122.0
offset_bottom = 34.0
text = "Dash Powerup"
[node name="SaveSpot" parent="." instance=ExtResource("10_tdtq1")]
position = Vector2(849, -352)
[node name="CollisionShape2D" type="CollisionShape2D" parent="SaveSpot"]
position = Vector2(1, 1)
shape = SubResource("RectangleShape2D_y1jh6")
[node name="Label" type="Label" parent="SaveSpot"]
offset_right = 40.0
offset_bottom = 23.0
text = "save spot"
[editable path="CameraFocusZone"] [editable path="CameraFocusZone"]