Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Графический интерфейс

Заключительный этап нашей игры нуждается в Пользовательском интерфейсе (UI), чтобы отображать такие вещи, как рейтинг, сообщение "игра окончена" и кнопку перезапуска.

Создайте новую сцену и добавьте узел CanvasLayer с именем HUD. "HUD" означает "heads-up display" ("графический интерфейс пользователя"), дисплей, отображающийся поверх игры.

Узел CanvasLayer позволяет нам прорисовывать элементы нашего UI на слое поверх всей остальной игры, поэтому отображаемая информация не перекрывается никакими игровыми элементами, такими как игрок или мобы.

HUD должен отображать следующую информацию:

  • Счет, измененный ScoreTimer.

  • Сообщение, например "Game Over" или "Get Ready!"

  • Кнопка "Start", чтобы начать игру.

Основной узел для элементов UI — это Control. Чтобы создать наш UI, мы будем использовать два типа узлов Control: Label и Button.

Создайте следующие узлы, как дочерние узла HUD:

  • Label с именем ScoreLabel.

  • Label с именем Message.

  • Button с именем StartButton.

  • Timer с именем MessageTimer.

Нажмите на ScoreLabel и введите число в поле Text в Инспекторе. Стандартный шрифт для узлов Control мал и плохо масштабируется. В ресурсы игры включен файл шрифта под названием "Xolonium-Regular.ttf". Чтобы использовать этот шрифт, сделайте следующее:

В "Theme Overrides > Fonts" выберите "Загрузить" и выберите файл "Xolonium-Regular.ttf".

../../_images/custom_font_load_font.webp

Размер шрифта все еще слишком мал, увеличьте его до 64 в разделе «Theme Overrides > Font Sizes». Сделав это для ScoreLabel, повторите изменения для узлов Message и StartButton.

../../_images/custom_font_size.webp

Примечание

Anchors: Control nodes have a position and size, but they also have anchors. Anchors define the origin - the reference point for the edges of the node.

Расположите узлы, как показано ниже. Вы можете перетаскивать узлы, чтобы разместить их вручную, или для более точного размещения используйте "Пресеты для значения якорей".

../../_images/ui_anchor.webp

ScoreLabеl

  1. Установите текст на 0.

  2. В Инспекторе, установите "Horizontal Alignment" и "Vertical Alignment" на Center.

  3. Установите "пресет якорей" на Вверху посередине.

Message

  1. Установите текст на Увернись от Крипов!.

  2. В Инспекторе, установите "Horizontal Alignment" и "Vertical Alignment" на Center.

  3. Установите "Autowrap Mode" на Word, в противном случае надпись останется на одной строке.

  4. В разделе "Control - Layout/Transform" установите для параметра «Size X» значение 480, чтобы использовать всю ширину экрана.

  5. Установите "Пресет якорей" на Центр.

StartButtоn

  1. Установите текст на Старт.

  2. В разделе "Control - Layout/Transform" установите для параметра «Size X» значение 480, а для параметра "Size Y" значение 100, чтобы добавить немного больше отступа между границей экрана и текстом.

  3. Установите "Пресет якорей " на Внизу посередине.

  4. В разделе "Control - Layout/Transform" установите для параметра "Position Y" значение 580.

В MessageTimer установите параметр Wait Time на 2, а параметр One Shot на значение "Вкл".

Теперь добавьте этот скрипт в HUD:

extends CanvasLayer

# Notifies `Main` node that the button has been pressed
signal start_game

Теперь мы хотим временно отобразить сообщение, например "Get Ready" (Приготовьтесь), поэтому мы добавляем следующий код

func show_message(text):
    $Message.text = text
    $Message.show()
    $MessageTimer.start()

Также нам нужна функция, которая будет вызываться, когда игрок проигрывает. Она покажет надпись "Game Over" на 2 секунды, затем произойдет возврат к основному экрану, и после короткой паузы появится кнопка "Старт".

func show_game_over():
    show_message("Game Over")
    # Wait until the MessageTimer has counted down.
    await $MessageTimer.timeout

    $Message.text = "Dodge the Creeps!"
    $Message.show()
    # Make a one-shot timer and wait for it to finish.
    await get_tree().create_timer(1.0).timeout
    $StartButton.show()

Эта функция вызывается, когда игрок проигрывает. Она покажет надпись "Game Over" на 2 секунды, затем произойдет возврат к основному экрану, и после короткой паузы появится кнопка "Start".

Примечание

Если вам нужно сделать паузу на короткое время, то альтернативой использованию узла Timer является использование функции SceneTree create_timer(). Может быть очень полезно добавлять задержки наподобие таких, как в вышеприведенном коде, где нам хотелось бы подождать немного времени, прежде чем показывать кнопку "Start".

Добавьте приведенный ниже код в HUD, чтобы обновлять счет

func update_score(score):
    $ScoreLabel.text = str(score)

Connect the pressed() signal of StartButton and the timeout() signal of MessageTimer, and add the following code to the new functions:

func _on_start_button_pressed():
    $StartButton.hide()
    start_game.emit()

func _on_message_timer_timeout():
    $Message.hide()

Подключение HUD к Main

Теперь, когда мы закончили создание сцены HUD, вернитесь к Main. Инстанцируйте сцену HUD в Main подобно тому, как вы это делали со сценой Player. Дерево сцены должно выглядеть так, поэтому убедитесь, что вы ничего не упустили:

../../_images/completed_main_scene.webp

Теперь нам нужно подключить функционал HUD в наш Main-скрипт. Для этого потребуются некоторые дополнения к сцене Main:

Во вкладке "Узел" присоедините сигнал HUD start_game к функции узла Main new_game(), введя "new_game" в поле "Принимающий метод" в окне "Присоединить сигнал к методу" . Убедитесь, что в скрипте рядом с функцией func new_game() теперь появилась зелёная иконка подключения.

В new_game() обновим отображение счёта и выведем сообщение "Get Ready":

$HUD.update_score(score)
$HUD.show_message("Get Ready")

В game_over() нам нужно вызвать соответствующую функцию HUD:

$HUD.show_game_over()

Наконец добавьте этот код в _on_score_Ttmer_timeout(), чтобы синхронизировать отображение с изменением количества очков:

$HUD.update_score(score)

Предупреждение

Когда вы убедитесь, что всё работает, удалите вызов new_game() из _ready(), иначе ваша игра запустится автоматически.

Теперь можно поиграть! Нажмите на кнопку "Запустить проект". Вам будет предложено выбрать основную сцену, выбирайте main.tscn.

Удаляем старых крипов

Если вы играете до "Game Over", а затем сразу начинаете новую игру, то крипы из предыдущей игры могут все еще оставаться на экране. Было бы лучше, если бы все они исчезали в начале новой игры. Нам просто нужен способ сказать всем мобам, чтобы они удалились. Мы можем сделать это с помощью функции "group" ("группа").

В сцене Mob выберите корневой узел и нажмите вкладку "Узел" рядом с Инспектором (там же, где вы находите сигналы узла). Рядом с "Сигналы" нажмите "Группы", введите новое имя группы и нажмите "Добавить".

../../_images/group_tab.webp

Теперь все мобы будут в группе "mobs". Затем мы можем добавить следующие строки к функции new_game() в Main:

get_tree().call_group("mobs", "queue_free")

Функция call_group() вызывает каждую именованную функцию на каждом узле в группе - в этом случае мы говорим каждому мобу удалять себя.

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