0

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."

asked Jun 11, 2024 at 12:41
8
  • What line is the error occuring on? Unless the checkpoints themselves are CharacterBody2Ds, you don't seem to be calling global_position on one. Commented Jun 11, 2024 at 17:04
  • The error is related to the load and save checkpoint functions. I made some corrections to the code, now it is as shown above, it is returning "Checkpoint file does not exist". When closing the game and returning, it still does not start from the last reached checkpoint. Commented Jun 12, 2024 at 11:28
  • So is it not returning "Checkpoint file does not exist" anymore? From what I can tell from your code, if the issue is it can't find the file, then the file either doesn't exist or isn't where the program expects it to be. Otherwise, it's a different issue. Commented Jun 12, 2024 at 12:28
  • If it is a case of the program checking a different file path, "user://" goes to 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. Commented Jun 12, 2024 at 12:30
  • He returns that the checkpoint was not found, as if it didn't exist. In the mentioned folder, there are also no files. The reason might be a matter of "persistence"? While researching online about this, I realized I haven't gone through a similar process before. Do you know how this works? Commented Jun 12, 2024 at 13:53

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.