基础的Save和Load功能

在GUI下创建新的文件夹pause_menu

  • 创建新的文件夹以及场景和脚本,名称都为pause_menu
    • 创建一些节点来描述页面
    • Process下的mode要选择Always
  • 将pause_menu场景加载到Autoload中
  • 编写pause_menu.gd代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    extends CanvasLayer

    @onready var button_save: Button = $VBoxContainer/Button_Save
    @onready var button_load: Button = $VBoxContainer/Button_Load

    var is_paused: bool = false

    func _ready() -> void:
    hide_pause_menu()
    button_load.pressed.connect(_on_load_pressed)
    button_save.pressed.connect(_on_save_pressed)
    pass

    func _unhandled_input(event: InputEvent) -> void:
    if event.is_action_pressed("pause"):
    if is_paused == false:
    show_pause_menu()
    pass
    else:
    hide_pause_menu()
    pass
    get_viewport().set_input_as_handled()

    func show_pause_menu():
    get_tree().paused = true
    visible = true
    is_paused = true
    button_save.grab_focus()
    pass

    func hide_pause_menu():
    get_tree().paused = false
    visible = false
    is_paused = false
    pass

    func _on_save_pressed() -> void:
    if is_paused == false:
    return
    SaveManager.save_game()
    hide_pause_menu()
    pass

    func _on_load_pressed() -> void:
    if is_paused == false:
    return
    SaveManager.load_game()
    hide_pause_menu()
    pass

  • 创建一个全局的save_manager
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    extends Node

    const SAVE_PATH = "user://"

    signal game_loaded
    signal game_saved

    var current_save: Dictionary = {
    scene_path = "",
    player = {
    hp = 1,
    max_hp = 1,
    pos_x = 0,
    pos_y = 0
    },
    items = [],
    persistence = [],
    quests = []
    }

    func save_game() -> void:
    update_player_data()
    update_scene_path()
    var file := FileAccess.open(SAVE_PATH + "save.sav", FileAccess.WRITE)
    var save_json = JSON.stringify(current_save)
    file.store_line(save_json)
    game_saved.emit()
    pass

    func load_game() -> void:
    var file := FileAccess.open(SAVE_PATH + "save.sav", FileAccess.READ)
    var json := JSON.new()
    json.parse(file.get_line())
    var save_dict: Dictionary = json.get_data() as Dictionary
    current_save = save_dict

    LevelManager.load_new_level(current_save.scene_path, "", Vector2.ZERO)

    await LevelManager.LevelLoadStarted

    PlayerManager.set_player_position(Vector2(current_save.player.pos_x,current_save.player.pos_y))
    PlayerManager.set_health(current_save.player.hp, current_save.player.max_hp)

    await LevelManager.LevelLoaded
    pass

    func update_player_data() -> void:
    var p: Player = PlayerManager.player
    current_save.player.hp = p.hp
    current_save.player.max_hp = p.max_hp
    current_save.player.pos_x = p.global_position.x
    current_save.player.pos_y = p.global_position.y
    pass

    func update_scene_path() -> void:
    var p: String = ""
    for c in get_tree().root.get_children():
    if c is Level:
    p = c.scene_file_path
    current_save.scene_path = p
    pass
    extends Node

    const SAVE_PATH = "user://"

    signal game_loaded
    signal game_saved

    var current_save: Dictionary = {
    scene_path = "",
    player = {
    hp = 1,
    max_hp = 1,
    pos_x = 0,
    pos_y = 0
    },
    items = [],
    persistence = [],
    quests = []
    }

    func save_game() -> void:
    update_player_data()
    update_scene_path()
    var file := FileAccess.open(SAVE_PATH + "save.sav", FileAccess.WRITE)
    var save_json = JSON.stringify(current_save)
    file.store_line(save_json)
    game_saved.emit()
    pass

    func load_game() -> void:
    var file := FileAccess.open(SAVE_PATH + "save.sav", FileAccess.READ)
    var json := JSON.new()
    json.parse(file.get_line())
    var save_dict: Dictionary = json.get_data() as Dictionary
    current_save = save_dict

    LevelManager.load_new_level(current_save.scene_path, "", Vector2.ZERO)

    await LevelManager.LevelLoadStarted

    PlayerManager.set_player_position(Vector2(current_save.player.pos_x,current_save.player.pos_y))
    PlayerManager.set_health(current_save.player.hp, current_save.player.max_hp)

    await LevelManager.LevelLoaded
    pass

    func update_player_data() -> void:
    var p: Player = PlayerManager.player
    current_save.player.hp = p.hp
    current_save.player.max_hp = p.max_hp
    current_save.player.pos_x = p.global_position.x
    current_save.player.pos_y = p.global_position.y
    pass

    func update_scene_path() -> void:
    var p: String = ""
    for c in get_tree().root.get_children():
    if c is Level:
    p = c.scene_file_path
    current_save.scene_path = p
    pass

鼠标问题

  • 由于playerHud层在保存层上方,所以鼠标没有办法直接点击到按钮,如果需要的话可以将PlayerHud层的Mouse->Filter设置乘Ignore