Поверхневий екран

Остання частина, яка потрібна нашій грі, - це інтерфейс користувача (UI) для відображення таких речей, як рахунок, повідомлення "гра завершена" та кнопка перезавантаження.

Створіть нову сцену та додайте вузол CanvasLayer з іменем HUD. "HUD" означає "head-up display" , інформаційний екран, який відображається поверх ігрового вікна.

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

HUD повинен відобразити наступну інформацію:

  • Рахунок, змінюваний ScoreTimer.

  • Повідомлення, наприклад "Game Over" ("Гра закінчена"), або "Get Ready!" ("Готуйся!")

  • Кнопка "Start"("Старт"), щоб розпочати гру.

Основний вузол для елементів інтерфейсу - Control. Для створення нашого інтерфейсу ми будемо використовувати два типи цього вузла : Label та Button.

Додайте вузлу HUD таких нащадків:

  • Label названа ScoreLabel (Мітка рахунку).

  • Label названа ``Message``( повідомлення).

  • Button названа StartButton (кнопка старту).

  • Timer названий MessageTimer (таймер повідомлення).

Клацніть на ScoreLabel і введіть число в поле Text в Інспекторі. Шрифт за замовчуванням для вузлів Control невеликий і не дуже масштабується. У ігрових активах є файл шрифту, який називається "Xolonium-Regular.ttf" (даний шрифт підтримує кирилицю). Щоб використовувати цей шрифт, виконайте наступне:

  1. У розділі Theme overrides > Fonts (Визначення теми > Шрифти) в порожній графі виберіть "New DynamicFont" ("Новий динамічний шрифт")

../../_images/custom_font1.png
  1. Клацніть на доданому "DynamicFont", а під Font > FontData (Шрифт > Дані шрифту) виберіть "Завантажити" та виберіть файл "Xolonium-Regular.ttf".

../../_images/custom_font2.png

Встановіть властивість Size в "Settings" на 64 для кращого вигляду.

../../_images/custom_font3.png

Зробивши це зі ScoreLabel ви можете натиснути стрілку вниз поряд з властивістю DynamicFont і вибрати "Копіювати", а потім "Вставити" його в тому ж місці на других вузлах Control.

Примітка

Прив'язки та поля: вузли Control мають положення та розмір, але вони також мають прив'язки (якорі) та поля. Прив'язки визначають початок координат - опорну точку для країв вузла. Поля оновлюються автоматично під час переміщення, чи зміни розміру, контрольного вузла. Вони представляють відстань від країв контрольного вузла до його прив'язки. Детальнішу інформацію дивіться doc_design_interfaces_with_the_control_nodes.

Впорядкуйте вузли, як показано нижче. Натисніть кнопку "Макет", щоб встановити макет вузла керування:

../../_images/ui_anchor.png

Ви можете перетягнути вузли, щоб розмістити їх вручну, або, для точнішого розміщення, скористайтеся такими налаштуваннями:

ScoreLabel (Мітка рахунку)

  • Макет : "Згори за шириною"

  • Text : 0

  • Align (вирівнювання): "Center"

Повідомлення

  • Макет : "Гор. за центром за шириною"

  • Text : Dodge the Creeps! (Ухились від крипів!)

  • Align (вирівнювання): "Center"

  • Autowrap (Авто-згортання) : "Увімкнено"

StartButton (Кнопка Старту)

  • Text : Старт

  • Макет : "За центром внизу "

  • Margin (Поле) :

    • Top (зверху): -200

    • Bottom (Знизу): -100

На MessageTimer, встановіть Wait Time (Час затримки) на 2 і встановіть властивість One Shot на "Увімкнено".

Тепер додайте скрипт до HUD:

extends CanvasLayer

signal start_game

Сигнал start_game вказує вузлу Main, що кнопка була натиснута.

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

Ця функція буде викликатися тоді, коли ми хочемо показати повідомлення тимчасово, наприклад, "Приготуйся".

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

    $Message.text = "Dodge the\nCreeps!"
    $Message.show()
    # Make a one-shot timer and wait for it to finish.
    yield(get_tree().create_timer(1), "timeout")
    $StartButton.show()

Ця функція викликається, коли гравець програє. Вона показує напис "Game Over" протягом 2 секунд, потім повертає екран заголовка і, після короткої паузи, покаже кнопку "Старт".

Примітка

Коли вам потрібно зробити паузу на короткий час, альтернативою використанню вузла Timer є використання функції SceneTree (Дерева Сцени) create_timer(). Це може бути дуже корисно для такої затримки, як, наприклад, у наведеному вище коді, де ми хочемо зачекати трохи часу, перш ніж показувати кнопку "Старт".

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

Ця функція викликається Main щоразу, коли рахунок змінюється.

Підключіть сигнал timeout() від MessageTimer і сигнал pressed() від StartButton та додайте наступний код до нових функцій:

func _on_StartButton_pressed():
    $StartButton.hide()
    emit_signal("start_game")

func _on_MessageTimer_timeout():
    $Message.hide()

Підключення HUD до Main

Тепер, коли ми закінчили створення сцени HUD, збережіть її та поверніться до Main. Вставте HUD сцену в Main, як ви вставили сцену Player. Повне дерево має виглядати так, тож переконайтеся, що ви нічого не пропустили:

../../_images/completed_main_scene.png

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

На вкладці Вузол приєднайте сигнал HUD start_game до функції new_game() вузла Main ввівши "new_game" в "Receiver Method" у вікні "Під'єднання сигналу". Переконайтеся, що в скрипті поряд з func new_game() появилася зелена іконка підключення.

У new_game() поновіть відображення рахунку і покажіть повідомлення "Get Ready" ("Приготуйся"):

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

У game_over() нам потрібно викликати відповідну функцію HUD:

$HUD.show_game_over()

Нарешті, додайте це до _on_ScoreTimer_timeout() для синхронізації відображення рахунку зі зміною рахунку:

$HUD.update_score(score)

Тепер ви готові грати! Натисніть кнопку "Відтворити проєкт". Вам буде запропоновано вибрати головну сцену, тому виберіть Main.tscn.

Видалення старих крипів

Якщо ви дограєте до кінця гри, а потім починаєте нову гру, крипи з попередньої гри все ще залишаються на екрані. Було б краще, якби вони всі зникли на початку нової гри. Нам просто потрібно сказати всім мобам, що вони мають знищитися. Ми можемо зробити це за допомогою функції "group" (група).

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

../../_images/group_tab.png

Тепер всі моби будуть в групі "mobs". Ми можемо додати наступні рядки до функції game_over() в Main:

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

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

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