адресація

адресація



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

Ідентифікатори

Defold використовує адреси (або URL-адреси, але давайте ігноруватимемо це зараз) для позначення ігрових об'єктів та компонентів. Ці адреси складаються з ідентифікаторів. Нижче наведено приклади того, як Defold використовує адреси. Завдяки цьому посібнику ми детально розглянемо, як вони працюють:
local id = factory.create("#enemy_factory")
label.set_text("my_gameobject#my_label", "Hello World!")

local pos = go.get_position("my_gameobject")
go.set_position(pos, "/level/stuff/other_gameobject")

msg.post("#", "hello_there")
local id = go.get_id(".")
Почнемо з дуже простого прикладу. Припустимо, що у вас є об'єкт гри з одним компонентом спрайт. У вас також є компонент сценарію для керування об'єктом гри. Налаштування в редакторі виглядатиме так:
bean in editor
Тепер ви хочете вимкнути спрайт під час початку гри, щоб ви могли зробити це пізніше. Це легко зробити, поставивши наступний код в "controller.script":
function init(self)
    msg.post("#body", "disable") 
end


  • Не хвилюйтеся, якщо ви здивовані символом "#". Ми підійдемо до цього найближчим часом.
Це буде працювати, як очікувалося. Коли гру починається, компонент сценарію належить до компоненту sprite за ідентифікатором "body" і використовує цю адресу, щоб надіслати йому повідомлення з "disable". Ефект цього спеціального повідомлення двигуна полягає в тому, що sprite компонент ховає спрайт-графіку. Схематично налаштування виглядають так:
bean
Ідентифікатори в налаштуваннях є довільними. Тут ми вирішили надати об'єкту гри ідентифікатор "bean", його компонент sprite був названий "body", а компонент сценарію, який керує символом, був названий "controller".

Якщо ви не виберете ім'я, редактор буде. Кожного разу, коли ви створюєте новий гра-об'єкт або компонент у редакторі,
унікальний ідентифікатор Id автоматично встановлюється.
Ігрові об'єкти автоматично отримують ідентифікатор, який називається "ходити" за допомогою переліку ("go2", "go3" тощо).
Компоненти отримують ідентифікатор, що відповідає типу компонента ("sprite", "sprite2" тощо).

Ви можете дотримуватися цих автоматично призначених імен, якщо хочете, але ми радимо вам змінити ідентифікатори належним чином,
описові назви

Тепер давайте додамо ще один компонент спрайту і надамо бобу щит:

bean
Новий компонент повинен бути однозначно ідентифікований в об'єкті гри. Якщо б ви надали йому назву "тіло", код скрипта буде неоднозначним щодо того, який спрайт повинен надіслати повідомлення "відключити". Тому ми вибираємо унікальний (і описовий) ідентифікатор "щит". Тепер ми можемо включити та відключити "тіло" та "щит" спрайти за бажанням.

bean
If you do try to use an identifier more than once, the editor will signal an error so this is never a problem in practice:
bean
Тепер давайте подивимося, що станеться, якщо ви додаєте більше об'єктів гри. Припустімо, ви хочете об'єднати дві "боби" у невелику команду. Ви вирішили називати один з іграшкових об'єктів "bean", а інший - "приятелем". Крім того, коли "боб" простояв деякий час, він повинен сказати "приятель", щоб почати танцювати.
Це відбувається шляхом відправлення користувацького повідомлення "dance" з компонента скрипта "controller" у "bean" до скрипту "controller" у "buddy":

bean
There are two separate components named “controller”, one in each game object but this is perfectly legal since each game object creates a new naming context.
Оскільки адресат повідомлення знаходиться поза об'єктом гри, що посилає повідомлення ("bean"), код повинен вказати, який "контролер" повинен отримати повідомлення. Потрібно вказати як ідентифікатор об'єкта цільової гри, так і ідентифікатор компонента.
Повна адреса до компонента стає "buddy # controller", і ця адреса складається з двох окремих частин.

  • По-перше, ідентичність об'єкта цільової гри ("buddy "),
  • потім слідує символ розділювача об'єкта / компонента гри ("#"),
  • і, нарешті, ви пишете ідентичність цільового компонента ("controller").
Повертаючись до попереднього прикладу з єдиним об'єктом гри, ми бачимо, що, залишивши частину ідентифікатора ігрового об'єкта цільової адреси, код може адресувати компоненти в поточному об'єкті гри.

Наприклад, "#body" позначає адресу компоненту "body" у поточному об'єкті гри.
Це дуже корисно, тому що цей код буде працювати в будь-якому об'єкті гри, поки присутній компонент "body".

Collections

Колекції дають змогу створювати групи або ієрархії об'єктів гри та використовувати їх у контрольованому режимі. Ви використовуєте файли збірки у вигляді шаблонів (або "прототипів" або "prefabs") у редакторі, коли ви заповнюєте свою гру вмістом.

Припустімо, що ви хочете створити велику кількість команд бен / друзів.
Хороший спосіб це зробити - створити шаблон у новому файлі колекції (ім'я це "team.collection"). Побудуйте об'єкт команди в колекційному файлі та збережіть його. Потім введіть екземпляр вмісту файлу збірки у ваш головний набір початкової завантаження та надішліть екземпляру ідентифікатор (name it "team_1"):
bean
За допомогою цієї структури об'єкт гри "bean" все ще може посилатися на компонент "controller" у "buddy" за адресою "buddy # controller".

bean
І якщо ви додаєте другий екземпляр команди "team.collection" (ім'я "team_2"), то код, який працює всередині компоненти скрипту "team_2", буде працювати так само. Екземпляр об'єкту гри "боб" з колекції "team_2" все ще може звертатися до компоненту "controller" у "друзі" за адресою "buddy # controller".

bean

Відносна адресація

Адреса "buddy # controller" працює для ігрових об'єктів у обох колекціях, оскільки це відносна адреса. Кожна зі збірників "team_1" і "team_2" створює новий контекст іменування або "простір імен", якщо ви хочете. Defold уникає зіткнень назв, приймаючи контекст іменування, який створює колекція для розгляду:

relative id
  • В контексті іменування "team_1" об'єктні ігри "bean" і "buddy" однозначно ідентифікуються.
  • Аналогічним чином, в контексті іменування "team_2" об'єкт гри "bean" і "buddy" також однозначно ідентифікуються.

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

скорочення 

Defold передбачає два корисні відносні скорочення для адреси:

.
Скорочення вирішення поточного об'єкта гри.
#
Скорочення вирішення до поточного компонента.
Наприклад
:

 -- Let this game object acquire input focus
 msg.post(".", "acquire_input_focus")
 -- Post "reset" to the current script
 msg.post("#", "reset")

шляхи ігрових об'єктів

Щоб правильно зрозуміти механізм іменування, давайте подивимося, що відбувається під час створення та запуску проекту:
  • Редактор читає збірку завантажувачів ("main.collection") та весь його вміст (ігрові об'єкти та інші колекції).
  • Для кожного статичного об'єкта гри компілятор створює ідентифікатор. Вони побудовані як "шляхи", починаючи з кореневого завантажувача, вниз ієрархія збірки до об'єкта. На кожному рівні додано символ '/'.
У нашому прикладі вище, гра буде працювати з наступними 4 ігрових об'єктів:
  • /team_1/bean
  • /team_1/buddy
  • /team_2/bean
  • /team_2/buddy
Identities are stored as hashed values. The runtime also stores the hash state for each collection identity which is used to continue hashing relative string to an absolute id.
У середовищі виконання групування збірки не існує. Неможливо дізнатися, яка колекція певного об'єкта гри належала до складання. Також не можна маніпулювати всіма об'єктами в колекції одночасно. Якщо вам потрібно виконувати такі операції, ви можете легко зробити відстеження себе в коді. Ідентифікатор кожного об'єкта є статичним
це гарантовано залишається фіксованим протягом усього терміну служби об'єкта. Це означає, що ви можете безпечно зберігати особистість об'єкта та використовувати його пізніше.

Абсолютна адресація

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

Наприклад, припустімо, що ви хочете, щоб менеджер AI відслідковував стан кожного об'єкта bean.
Ви хочете, щоб боби звітували про свій активний стан менеджером, і менеджер приймає тактичні рішення і наказує бобам на підставі їх статусу. У цьому випадку ідеально було б створити єдиний об'єкт управління гравцям з компонентом скрипту і розмістити його поряд із колекцій колекції у збірці завантажувачів.
manager object
Тоді кожний бен відповідає за надсилання повідомлень про статус менеджеру: "контакт", якщо воно потрапляє до ворога або "оуч!", Якщо він потрапляє і потрапить на шкоду. Для того, щоб працювати, сценарії контролера bean використовують абсолютну адресацію, щоб відправляти повідомлення до компонента "controller" в "manager".
Будь-яка адреса, що починається з "/", буде вирішена з кореня ігрового світу. Це відповідає коренем колекції завантажувачів, завантаженим під час початку гри.

Абсолютна адреса сценарію менеджера - "/ manager # controller", і ця абсолютна адреса буде вирішена до потрібного компонента незалежно від того, де він використовується.
teams and manager
absolute addressing

Хеш-ідентифікатори

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

Коли ви отримаєте ідентифікатор об'єкта гри, двигун завжди повертає ідентифікатор абсолютного шляху, який є хешуванням:

local my_id = go.get_id()
print(my_id) --> hash: [/path/to/the/object]

local spawned_id = factory.create("#some_factory")
print(spawned_id) --> hash: [/instance42]
Ви можете використовувати такий ідентифікатор замість ідентифікатора рядка або створити його самостійно. Зауважте, що хедж-ідентифікатор відповідає шляху до об'єкта, тобто абсолютну адресу:

The reason relative addresses must be given as strings is because the engine will compute a new hash id based on the hash state of the current naming context (collection) with the given string added to the hash.
local spawned_id = factory.create("#some_factory")
local pos = vmath.vector3(100, 100, 0)
go.set_position(pos, spawned_id)

local other_id = hash("/path/to/the/object")
go.set_position(pos, other_id)

-- This will not work! Relative addresses must be given as strings.
local relative_id = hash("my_object")
go.set_position(pos, relative_id)

URLs

Щоб завершити зображення, давайте розглянемо повний формат адрес Defold: URL.

URL - це об'єкт, який зазвичай записується як спеціально відформатовані рядки. Загальний URL складається з трьох частин:

[socket:][path][#fragment]
socket
Визначає ігровий світ цілі. Це важливо при роботі з Collection Proxies, а потім використовується для ідентифікації динамічно завантаженої колекції.
path
Ця частина URL-адреси містить повний ідентифікатор об'єкта цільової гри.
fragment
Ідентифікація цільового компонента у вказаному об'єкті гри.
Як ми вже бачили вище, ви можете залишити деякі або більшу частину цієї інформації в більшості випадків. Вам майже ніколи не потрібно вказувати сокет, і вам часто, але не завжди, потрібно вказати шлях. У тих випадках, коли вам потрібно вирішити речі в іншому ігровому світі, тоді потрібно вказати частину розеток URL-адреси. Наприклад,
повне URL рядок для сценарію "контролер" в об'єкті гри "менеджер" вище:
"main:/manager#controller"
і контролер команди buddy у команді_2:
"main:/team_2/buddy#controller"
Ми можемо надсилати їм повідомлення:
-- Send "hello" to the manager script and team buddy bean
msg.post("main:/manager#controller", "hello_manager")
msg.post("main:/team_2/buddy#controller", "hello_buddy")

Побудова URL-адрес об'єктів


Об'єкти URL-адреси також можуть бути побудовані програмно в коді Lua:
-- Construct URL object from a string:
local my_url = msg.url("main:/manager#controller")
print(my_url) --> url: [main:/manager#controller]
print(my_url.socket) --> 786443 (internal numeric value)
print(my_url.path) --> hash: [/manager]
print(my_url.fragment) --> hash: [controller]

-- Construct URL from parameters:
local my_url = msg.url("main", "/manager", "controller")
print(my_url) --> url: [main:/manager#controller]

-- Build from empty URL object:
local my_url = msg.url()
my_url.socket = "main" -- specify by valid name
my_url.path = hash("/manager") -- specify as string or hash
my_url.fragment = "controller" -- specify as string or hash

-- Post to target specified by URL
msg.post(my_url, "hello_manager!")

Немає коментарів:

Дописати коментар

Kоментарі неуkраїнсьkою видалятимуться