*Вы можете найти ссылки на предыдущие части в нижней части этого руководства.

Одной из основных частей любой игры является пауза и главное меню. Главное меню — это первый экран, который ваш игрок увидит при запуске игры, а меню паузы приостановит игру, когда игрок нажмет кнопку, например «ESC». В нашей игре мы хотим, чтобы главное меню позволяло игроку начать новую игру, загрузить сохраненную игру или полностью выйти из игры. В нашем меню паузы мы хотим, чтобы игрок мог возобновить свой уровень, сохранить свой текущий уровень, перезагрузить свой текущий уровень и выйти на экран главного меню.

ШАГ 1. ИНТЕРФЕЙС МЕНЮ ПАУЗЫ

В нашу сцену Player давайте добавим новый узел CanvasLayer с именем «PauseMenu».

Добавьте к нему узел ColorRect и назовите его «Меню». Измените пресет привязки этого меню на полный прямоугольник и измените его цвет на #834040.

Добавьте еще один узел ColorRect в узел меню и назовите его «Контейнер». Измените его цвет на #964545, размер на (x: 1078, y: 580) и положение на (x: 35, y: 25).

Скопируйте и вставьте узлы TileMap, AnimatedKing и AnimatedPig из узла GameOver в узел PauseMenu/Menu.

Давайте изменим анимацию AnimatedPig на все кадры из спрайт-листа «res://Assets/Kings and Pigs/Sprites/06-Pig Hide in the Box/Looking Out (26x20).png». Измените FPS на «4» и оставьте цикл включенным.

Измените анимацию AnimatedKing на все кадры из таблицы спрайтов «res://Assets/Kings and Pigs/Sprites/01-King Human/Idle (78x58).png». Измените FPS на «11» и оставьте цикл включенным.

Сделайте TileMap немного другим и переместите Короля и Свинью туда, где вы хотите.

Теперь к узлу PauseMenu/Menu/Container добавьте четыре узла Button и один узел Label. Организуйте и переименуйте их, как показано на изображении ниже.

1. Ярлык

Выберите узел «Ярлык» и измените его текст на «Меню паузы». Его шрифт должен быть «QuinqueFive», а размер шрифта должен быть 35. Также измените его положение на (x: 299, y: 20).

2. Кнопка возобновления

Выберите узел ButtonResume и измените его текст на «Уровень возобновления». Его шрифт должен быть «QuinqueFive», а размер шрифта должен быть 25. Измените цвет шрифта на #d98c8a. Также измените его размер на (x: 500, y: 80) и его положение на (x: 285, y: 100).

3. Кнопка Сохранить

Выберите узел ButtonSave и измените его текст на «Save Level». Его шрифт должен быть «QuinqueFive», а размер шрифта должен быть 25. Измените цвет шрифта на #d98c8a. Также измените его размер на (x: 500, y: 80) и его положение на (x: 285, y: 200).

4. Кнопка загрузки

Выберите узел ButtonLoad и измените его текст на «Уровень нагрузки». Его шрифт должен быть «QuinqueFive», а размер шрифта должен быть 25. Измените цвет шрифта на #d98c8a. Также измените его размер на (x: 500, y: 80) и его положение на (x: 285, y: 300).

5. КнопкаВыход

Выберите узел ButtonQuit и измените его текст на «Уровень выхода». Его шрифт должен быть «QuinqueFive», а размер шрифта должен быть 25. Измените цвет шрифта на #d98c8a. Также измените его размер на (x: 500, y: 80) и его положение на (x: 285, y: 400).

Теперь подключите все сигналы pressed() четырех кнопок к скрипту Player.

Измените видимость узла PauseMenu, чтобы он был скрыт.

Наконец, нам нужно изменить режим обработки нашего узла PauseMenu на «При паузе», так как мы хотим, чтобы он принимал ввод только тогда, когда игра приостановлена, и никакие другие узлы не нуждаются в доступе к нему, когда игра не приостановлена.

ШАГ 2. Интерфейс ГЛАВНОГО МЕНЮ

Скопируйте ветку узла PauseMenu из сцены Player и создайте новую сцену с помощью параметра «Вставить из буфера обмена».

Переименуйте корневой узел в «MainMenu» и сохраните сцену как «MainMenu» в папке «Сцены».

Теперь удалите один узел Button и переименуйте оставшиеся три, как показано на изображении ниже.

Прикрепите новый скрипт к сцене MainMenu и сохраните его в папке Scripts.

Отключите и снова подключите сигнальные соединения pressed() на всех трех ваших кнопках, чтобы они были подключены к вашему сценарию MainMenu.

Затем измените режим обработки корневого узла MainMenu на «Всегда».

1. Ярлык

Выберите узел Label и измените его текст на Castle Climber. Его шрифт должен быть «QuinqueFive», а размер шрифта должен быть 35. Также измените его положение на (x: 299, y: 20).

2. КнопкаСоздать

Выберите узел ButtonNew и измените его текст на «Новая игра». Его шрифт должен быть «QuinqueFive», а размер шрифта должен быть 30. Измените цвет шрифта на #d98c8a. Также измените его размер на (x: 500, y: 100) и его положение на (x: 285, y: 120).

3. Кнопка загрузки

Выберите узел ButtonLoad и измените его текст на «Загрузить игру». Его шрифт должен быть «QuinqueFive», а размер шрифта должен быть 30. Измените цвет шрифта на #d98c8a. Также измените его размер на (x: 500, y: 100) и его положение на (x: 285, y: 240).

4. КнопкаВыход

Выберите узел ButtonQuit и измените его текст на «Выход». Его шрифт должен быть «QuinqueFive», а размер шрифта должен быть 30. Измените цвет шрифта на #d98c8a. Также измените его размер на (x: 500, y: 100) и его положение на (x: 285, y: 360).

Вы можете изменить анимацию AnimatedKing и AnimatedPig на любую анимацию, которую захотите. Я продублировал свой узел AnimatedPig, чтобы он стал еще одной свиньей, которая стоит на нашем друге в коробке. Также нарисуйте тайловую карту, чтобы она отличалась от других экранов!

ШАГ 3: ФУНКЦИОНАЛЬНОСТЬ МЕНЮ ПАУЗЫ

Чтобы наше меню паузы отображалось, нам сначала нужно создать новый ввод с именем ui_pause, который откроет наше меню, если мы нажмем ввод, например «ESC».

В нашей функции input() давайте сделаем наше меню паузы видимым, когда игрок нажимает на наш только что созданный ввод. Мы также приостановим игру, чтобы наши игроки и спавнеры не обрабатывали данные.

### Player.gd

#older code

#singular input captures
func _input(event):
    #pause game
    if event.is_action_pressed("ui_pause"):
        #pause scene
        get_tree().paused = true
        #show menu
        $PauseMenu.visible = true

Затем в функции _on_button_resume_pressed() нашей кнопки возобновления мы возобновим игру и скроем меню.

### Player.gd

#older code

#resume game
func _on_button_resume_pressed():
    #unpause scene
    get_tree().paused = false
    #hide menu
    $PauseMenu.visible = false

Затем мы изменим нашу сцену обратно на нашу сцену MainMenu, если игрок нажмет нашу кнопку выхода. Мы внесем эти изменения в нашу функцию _on_button_quit_pressed().

### Player.gd

#older code

#quit to main menu  
func _on_button_quit_pressed():
    get_tree().change_scene_to_file("res://Scenes/MainMenu.tscn")

Мы добавим оставшуюся функциональность в наши _load_pressed() и _save_pressed() в следующей части, когда добавим систему сохранения/загрузки.

Теперь, если вы запустите свою сцену, вы сможете приостановить игру, возобновить ее, а также выйти из сцены MainMenu.

ШАГ 4: ФУНКЦИОНАЛЬНОСТЬ ГЛАВНОГО МЕНЮ

Чтобы выйти из нашей игры в нашей функции _on_button_quit_pressed(), мы можем просто вызвать метод quit(), который уничтожит и полностью закроет приложение.

### MainMenu.gd

#older code

#quit game
func _on_button_quit_pressed():
    get_tree().quit()

Теперь в нашей функции _on_button_new_pressed() нам сначала нужно очистить нашу текущую_сцену, в которой находится наш игрок. Нам нужно сделать это, чтобы убедиться, что наша текущая_сцена правильно удалена из памяти приложения, и, мы можем назначить новое значение current_scene, которое переопределит данные из предыдущего значения current_scene.

### MainMenu.gd

#older code

#starts a new game in the Main scene, which is our 1st level
func _on_button_new_pressed():
    # Get the current scene
    var current_scene = get_tree().current_scene
    # Free the current scene if it exists
    if current_scene:
        current_scene.queue_free()

После того, как мы удалили нашу текущую_сцену из нашей памяти, нам нужно создать новый экземпляр нашего первого уровня — это наша сцена Main.tscn.

### MainMenu.gd

#older code

#starts a new game in the Main scene, which is our 1st level
func _on_button_new_pressed():
    # Get the current scene
    var current_scene = get_tree().current_scene
    # Free the current scene if it exists
    if current_scene:
        current_scene.queue_free()
    # Load the new scene
    var new_scene = load("res://Scenes/Main.tscn").instantiate()

Затем нам нужно добавить эту экземплярную сцену в качестве дочерней к нашей новой сцене, потому что мы хотим, чтобы этот потомок был новым значением нашей переменной current_scene.

### MainMenu.gd
#older code

#starts a new game in the Main scene, which is our 1st level
func _on_button_new_pressed():
    # Get the current scene
    var current_scene = get_tree().current_scene
    # Free the current scene if it exists
    if current_scene:
        current_scene.queue_free()
    # Load the new scene
    var new_scene = load("res://Scenes/Main.tscn").instantiate()
    # Add the new scene as a child of the root node
    get_tree().root.add_child(new_scene)
    # Set the new scene as the current scene
    get_tree().set_current_scene(new_scene)
    # Update the global variable with the name of the new scene
    Global.current_scene_name = new_scene.name

Наконец, нам нужно снять игру с паузы, чтобы наша новая игра не запускалась в состоянии паузы.

### MainMenu.gd
#older code

#starts a new game in the Main scene, which is our 1st level
func _on_button_new_pressed():
    # Get the current scene
    var current_scene = get_tree().current_scene
    # Free the current scene if it exists
    if current_scene:
        current_scene.queue_free()
    # Load the new scene
    var new_scene = load("res://Scenes/Main.tscn").instantiate()
    # Add the new scene as a child of the root node
    get_tree().root.add_child(new_scene)
    # Set the new scene as the current scene
    get_tree().set_current_scene(new_scene)
    # Update the global variable with the name of the new scene
    Global.current_scene_name = new_scene.name
    # Ensures scene isn't paused
    get_tree().paused = false

Ваш код должен выглядеть как это.

Теперь, если вы запустите основную сцену, вы сможете начать новую игру, а также полностью выйти из нее.

Настроив основу нашего основного меню и меню паузы, мы можем перейти к следующей части, где мы добавим нашему игроку функциональность для сохранения и загрузки своей игры, что загрузит их на последний сохраненный уровень.

Сейчас самое время сохранить ваш проект и сделать резервную копию вашего проекта, чтобы вы могли вернуться к этой части, если возникнут какие-либо ошибки, нарушающие работу игры. Вернитесь и повторите то, что вы узнали, прежде чем продолжить серию, и как только вы будете готовы, увидимся в следующей части!

Следующая часть серии руководств

Учебная серия состоит из 24 глав. Я буду публиковать все главы в отдельных ежедневных частях в течение следующих нескольких недель. Вы можете найти обновленный список ссылок на учебники для всех 24 частей этой серии на моем GitBook. Если вы еще не видите ссылку, добавленную к части, это означает, что она еще не опубликована. Кроме того, если будут какие-либо будущие обновления серии, мой GitBook будет местом, где вы сможете быть в курсе всего!

Поддержите серию и получите ранний доступ!

Если вам нравится эта серия и вы хотите поддержать меня, вы можете пожертвовать любую сумму моему магазину KoFi или купить оффлайн PDF, в котором вся серия собрана в одном буклете, который можно взять с собой!

Брошюра дает вам пожизненный доступ к полной автономной версии брошюры «Изучайте Godot 4, создавая двухмерный платформер» в формате PDF. Это 451-страничный документ, содержащий все учебные пособия из этой серии в последовательном формате, а также вы получите от меня специальную помощь, если вы когда-нибудь застрянете или вам понадобится совет. Это означает, что вам не нужно ждать, пока я опубликую следующую часть серии руководств на Dev.to или Medium. Вы можете просто двигаться дальше и продолжать обучение в своем собственном темпе — в любое время и в любом месте!

Эта книга будет постоянно обновляться для исправления недавно обнаруженных ошибок или устранения проблем совместимости с более новыми версиями Godot 4.