Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Поява монстрів

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

image0

Двічі клацніть main.tscn у доку FileSystem, щоб відкрити сцену Main.

Перш ніж малювати шлях, ми збираємося змінити роздільну здатність гри. Наша гра має стандартний розмір вікна 1152x648. Ми встановимо для нього 720x540, гарне маленьке поле.

Перейдіть до Проект -> Параметри проекту.

image1

Якщо у вас Input Map все ще відкрита, переключіть вкладку на General.

У лівому меню перейдіть до пункту Дисплей -> Вікно. Праворуч встановіть для параметра Ширина області перегляду значення 720, а для параметра Висота області перегляду значення 540.

image2

Створення шляху на якому з'являтимуться монстри

Як і в підручнику з двовимірної гри, ви збираєтеся спроектувати шлях і використовувати вузол PathFollow3D для вибірки випадкових місць на ньому.

У 3D, однак, це трохи складніше. Ми хочемо, щоб він був навколо виду гри, щоб монстри з'являлися прямо за екраном. Але якщо ми намалюємо шлях, ми не побачимо його з попереднього перегляду камери.

Щоб знайти межі перегляду, ми можемо використовувати деякі сітки-заповнювачі. Ваше вікно перегляду все одно має бути розділене на дві частини, з попереднім переглядом камери внизу. Якщо це не так, натисніть Ctrl + 2 (Cmd + 2 на macOS), щоб розділити перегляд на два. Виберіть вузол Camera3D і натисніть прапорець Попередній перегляд у нижньому вікні перегляду.

image3

Додавання циліндрів-орієнтирів

Додамо сіті-заповнювачі. Додайте новий Node3D як дочірню вершину Main і назвіть її Cylinders. Ми будемо використовувати його для групування циліндрів. Виділіть Cylinders і додайте дочірній вузол MeshInstance3D

image4

В Інспекторі властивості Mesh призначте CylinderMesh.

image5

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

image6

Сітка може відволікати. Ви можете перемкнути його, перейшовши до меню Перегляд на панелі інструментів і натиснувши Перегляд сітки.

image7

Тепер вам треба перемістити циліндр вздовж наземної площини, дивлячись на попередній перегляд камери в нижньому вікні перегляду. Я рекомендую робити це використовуючи прив'язку до ґратки. Ви можете перемикати прив'язку, клацаючи значок магніту на панелі інструментів, або натискаючи Y.

image8

Перемістіть циліндр так, щоб він опинився поза полем зору камери у верхньому лівому куті.

image9

Ми збираємося створити копії меша і розмістити їх навколо ігрової зони. Натисніть Ctrl + D (Cmd + D на macOS), щоб дублювати вузол. Також можна клацнути правою кнопкою миші вузол на панелі Сцена та вибрати пункт Дублювати. Переміщуйте копію вниз по синій осі Z, доки вона не вийде за межі попереднього перегляду камери.

Виберіть обидва циліндри, натиснувши клавішу Shift і клацнувши по невибраному, і дублюйте їх.

image10

Перемістіть їх праворуч по червоній осі X.

image11

Білі циліндри трохи важко розгледіти, чи не так? Давайте виділимо їх, надавши їм новий матеріал.

У 3D матеріали визначають візуальні властивості поверхні, такі як її колір, те, як вона відбиває світло, тощо. Ми можемо використовувати їх для зміни кольору меша.

Ми можемо оновити всі чотири циліндри одночасно. Виберіть усі екземпляри сітки в доці Scene. Щоб зробити це, ви можете клацнути на першому та клацнути Shift на останньому.

image12

У Inspector розгорніть розділ Material і призначте StandardMaterial3D для слота 0.

image13

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

Розширте секцію Albedo.

../../_images/albedo_section.webp

Виберіть колір, який контрастує з фоном, наприклад, яскраво-помаранчевий.

image14

Тепер ми можемо використовувати циліндри в якості орієнтирів. Згорніть їх на панелі Сцена натиснувши сіру стрілку поруч з ними. Надалі, ви також можете перемикати їх видимість, клацнувши значок ока поруч із Cylinders.

image15

Додайте дочірній вузол Path3D до Main вузла. На панелі інструментів з'являються чотири значки. Натисніть інструмент Додати точку, значок із зеленим знаком «+».

image16

Примітка

Ви можете навести курсор на будь-яку піктограму, щоб побачити підказку з описом інструмента.

Клацніть по центру кожного циліндра, щоб створити точку. Потім клацніть піктограму Закрити криву на панелі інструментів, щоб закрити контур. Якщо якась точка трохи за межами, можете натиснути на неї і перетягнути, щоб змінити розташування.

image17

Ваш шлях повинен виглядати так.

image18

Для вибірки випадкових позицій на ньому нам потрібен вузол PathFollow3D. Додайте PathFollow3D як дочірній елемент Path3D. Перейменуйте два вузли на SpawnLocation і SpawnPath відповідно. Це більш опис того, для чого ми їх використовуватимемо.

image19

З усім цим ми готові кодувати механізм появи монстрів.

Поява монстрів

Клацніть правою кнопкою миші вузол Main і приєднайте до нього новий скрипт.

Спочатку ми експортуємо змінну в Inspector, щоб ми могли призначити їй mob.tscn або будь-якого іншого монстра.

extends Node

@export var mob_scene: PackedScene

Ми хочемо, щоб моби народжувалися через певні проміжки часу. Для цього нам потрібно повернутися на сцену і додати таймер. Але перед цим нам потрібно присвоїти файл mob.tscn властивості mob_scene вище (інакше вона буде нульовою!)

Поверніться до 3D-екрана та виберіть вузол Main. Перетягніть mob.tscn із дока FileSystem до слота Mob Scene в Inspector.

image20

Додайте новий вузол Timer як дочірній вузол Main. Назвіть його MobTimer.

image21

У Інспекторі встановіть час очікування Wait Time на 0.5 секунди та увімкніть автозапуск Autostart, щоб таймер автоматично запускався разом із грою.

image22

Таймери випромінюють сигнал timeout кожного разу, коли вони досягають кінця свого часу очікування Wait Time. За замовчуванням вони перезавантажуються автоматично, випромінюючи сигнал в циклі. Ми можемо підключатися до цього сигналу від головного вузла Main, щоб налаштувати появу монстрів кожні 0.5 секунди.

З вибраним MobTimer перейдіть до панелі Signals праворуч і двічі клацніть сигнал timeout.

image23

Підключіть його до головного вузла Main.

image24

Це поверне вас до сценарію з новою порожньою функцією _on_mob_timer_timeout().

Давайте кодувати логіку появи монстрів. Ми збираємося:

  1. Вставити екземпляр (інстансувати) сцени монстра.

  2. Отримати випадкове положення на шляху появи.

  3. Отримати позицію гравця.

  4. Викликати метод монстра initialize(), передаючи йому випадкову позицію і позицію гравця.

  5. Додати монстра в якості нащадка головного вузла Main.

func _on_mob_timer_timeout():
    # Create a new instance of the Mob scene.
    var mob = mob_scene.instantiate()

    # Choose a random location on the SpawnPath.
    # We store the reference to the SpawnLocation node.
    var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
    # And give it a random offset.
    mob_spawn_location.progress_ratio = randf()

    var player_position = $Player.position
    mob.initialize(mob_spawn_location.position, player_position)

    # Spawn the mob by adding it to the Main scene.
    add_child(mob)

Вище randf() створює випадкове значення між 0 і 1, що є тим, що очікує progress_ratio вузла PathFollow: 0 – початок шляху, 1 це кінець шляху. Шлях, який ми встановили, пролягає навколо вікна перегляду камери, тому будь-яке випадкове значення між 0 і 1 є випадковою позицією вздовж країв вікна перегляду!

Зазначте, що якщо ви вилучаєте Player з головної сцени, наступний рядок

var player_position = $Player.position

дасть помилку, тому що тут нема $Player!

Ось повний скрипт main.gd для довідки.

extends Node

@export var mob_scene: PackedScene


func _on_mob_timer_timeout():
    # Create a new instance of the Mob scene.
    var mob = mob_scene.instantiate()

    # Choose a random location on the SpawnPath.
    # We store the reference to the SpawnLocation node.
    var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
    # And give it a random offset.
    mob_spawn_location.progress_ratio = randf()

    var player_position = $Player.position
    mob.initialize(mob_spawn_location.position, player_position)

    # Spawn the mob by adding it to the Main scene.
    add_child(mob)

Ви можете протестувати сцену, натиснувши F6 (Cmd + R на macOS). Ви повинні побачити, як монстри з'являються та рухаються по прямій лінії.

image25

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