I’m new to game development and recently started developing my first game, a simple 2D game to better understand the platform’s functionalities.
I’m having trouble adjusting the checkpoint saving system in my game.
My game is returning the following error: 'Checkpoint file does not exist'
base image of my files, the scenes follow this pattern
The current code:
title_screen.gd (scene main):
extends Control
func _ready():
pass # Não é necessário implementar nada aqui
func _on_start_btn_pressed():
var checkpoint_data = Globals.load_checkpoint()
if checkpoint_data != null:
Globals.player.position = checkpoint_data.position
get_tree().change_scene_to_file(checkpoint_data.scene)
else:
get_tree().change_scene_to_file("res://levels/world_01.tscn")
func _on_new_btn_pressed():
get_tree().change_scene_to_file("res://levels/world_01.tscn")
func _on_credits_btn_pressed():
# Implemente conforme necessário
pass
func _on_quit_btn_pressed():
Globals.save_checkpoint()
get_tree().quit()
checkpoint.gd:
extends Area2D
var is_active = false
func _on_body_entered(body):
if body.name == "player" and not is_active:
activate_checkpoint()
func activate_checkpoint():
Globals.current_checkpoint = self
Globals.current_checkpoint_scene = get_tree().current_scene.get_path()
is_active = true
Globals.save_checkpoint()
globals.gd (global):
extends Node
var player = null
var current_checkpoint = null
var current_checkpoint_scene = ""
var checkpoint_save_path = "user://checkpoint.sav"
func _ready():
print("Globals script ready") # Adicione uma mensagem para depuração
load_checkpoint_from_file()
func _exit_tree():
print("Tree exiting, saving checkpoint") # Adicione uma mensagem para depuração
save_checkpoint()
func respawn_player():
if current_checkpoint != null:
player.position = current_checkpoint.global_position
func load_checkpoint():
if current_checkpoint != null:
return {
"position": current_checkpoint.global_position,
"scene": current_checkpoint_scene
}
return null
func save_checkpoint():
if current_checkpoint != null:
var file = FileAccess.open(checkpoint_save_path, FileAccess.WRITE)
if file:
file.store_pascal_string(current_checkpoint_scene)
file.store_var(current_checkpoint.global_position)
file.close()
print("Checkpoint saved: ", current_checkpoint_scene, current_checkpoint.global_position)
else:
print("Error opening file for writing")
func load_checkpoint_from_file():
if not FileAccess.file_exists(checkpoint_save_path):
print("Checkpoint file does not exist")
return
var file = FileAccess.open(checkpoint_save_path, FileAccess.READ)
if file:
current_checkpoint_scene = file.get_pascal_string()
var pos := file.get_var() as Vector2
file.close()
current_checkpoint = pos
print("Checkpoint loaded: ", current_checkpoint_scene, pos)
else:
print("Error opening file for reading")
goal.gd:
extends Area2D
@onready var transition = $"../transition"
@export var next_level : String = ""
func _on_body_entered(body):
if body.name == "player" and !next_level == "":
transition.change_scene(next_level)
else:
print("No Scene Loaded")
transition.gd:
extends CanvasLayer
@onready var color_rect = $color_rect
func _ready():
show_new_scene()
func change_scene(path: String, delay: float = 1.5):
var scene_transition = get_tree().create_tween()
scene_transition.tween_property(color_rect, "threshold", 1.0, 0.5).set_delay(delay)
await scene_transition.finished
assert(get_tree().change_scene_to_file(path) == OK)
func show_new_scene():
var show_transition = get_tree().create_tween()
show_transition.tween_property(color_rect, "threshold", 0.0, 0.5).from(1.0)
world.gd (Base/General):
extends Node2D
@onready var player := $player as CharacterBody2D
@onready var player_scene = preload("res://levels/player.tscn")
@onready var camera := $camera as Camera2D
# Called when the node enters the scene tree for the first time.
func _ready():
Globals.player = player
Globals.player.follow_camera(camera)
Globals.player.player_has_died.connect(reload_game)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass
func reload_game():
await get_tree().create_timer(1.0).timeout
var player = player_scene.instantiate()
add_child(player)
Globals.player = player
Globals.player.follow_camera(camera)
Globals.player.player_has_died.connect(reload_game)
Globals.respawn_player()
#get_tree().reload_current_scene()
player.gd:
extends CharacterBody2D
const SPEED = 130.0
const JUMP_VELOCITY = -300.0
var direction
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var is_jumping := false
signal player_has_died()
@onready var animation := $anim as AnimatedSprite2D
@onready var remote_transform := $remote as RemoteTransform2D
@onready var rip_effect = $rip_effect as AudioStreamPlayer
@onready var timer = $Timer
func _physics_process(delta):
# Add the gravity.
if not is_on_floor():
velocity.y += gravity * delta
# Handle jump.
if Input.is_action_just_pressed("ui_up") and is_on_floor():
velocity.y = JUMP_VELOCITY
is_jumping = true
elif is_on_floor():
is_jumping = false
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
direction = Input.get_axis("ui_left", "ui_right")
if direction != 0:
velocity.x = direction * SPEED
animation.scale.x = direction
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
_set_state()
move_and_slide()
func _on_hurtbox_body_entered(body):
if body.is_in_group("enemies"):
timer.wait_time = 0.5
timer.one_shot = true
rip_effect.play()
timer.start()
# Aguarda o Timer completar
await timer.timeout
emit_signal("player_has_died")
get_tree().reload_current_scene()
func follow_camera(camera):
var camera_path = camera.get_path()
remote_transform.remote_path = camera_path
func _set_state():
var state = "idle"
if !is_on_floor():
state = "jump"
elif direction != 0:
state = "run"
if animation.name != state:
animation.play(state)
func _input(event):
if event is InputEventScreenTouch:
if Input.is_action_just_pressed("ui_up") and is_on_floor():
velocity.y = JUMP_VELOCITY
is_jumping = true
elif is_on_floor():
is_jumping = false
I would like the player to be able to continue from the last checkpoint reached when they close the game, return, and click "start."
CharacterBody2Ds, you don't seem to be calling global_position on one.C:\Users\<username>\AppData\Roaming\Godot\app_userdata\<name of godot project>. Although, as long as the save function is being called first, that shouldn't be the issue.