This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
Рушій перехоплює всі дані введення користувача й передає їх як дії компонентам-скриптам (script components) і компонентам зі скриптами GUI в ігрових об’єктах (game objects), які отримали фокус введення та реалізують функцію on_input(). Цей посібник пояснює, як налаштувати прив’язки для перехоплення введення та написати код, що на нього реагує.
Система введення спирається на набір простих і потужних понять, завдяки яким ви можете керувати введенням відповідно до потреб своєї гри.

Прив’язки введення — це спільна для всього проєкту таблиця, у якій ви задаєте, як введення з пристроїв перетворюється на іменовані дії, перш ніж їх буде передано компонентам-скриптам і скриптам GUI. Щоб створити новий файл прив’язок введення, клацніть правою кнопкою миші потрібне місце на панелі Assets і виберіть New... ▸ Input Binding. Щоб рушій використовував новий файл, змініть значення Game Binding у game.project.

Стандартний файл прив’язок введення автоматично створюється в усіх шаблонах нових проєктів, тому зазвичай створювати новий файл прив’язок не потрібно. Стандартний файл має назву game.input_binding і розташований у папці input у корені проєкту. Двічі клацніть файл, щоб відкрити його в редакторі:

Щоб створити нову прив’язку, натисніть кнопку + унизу розділу відповідного типу тригерів. Кожен запис має два поля:
A геймпада до дії jump. Зауважте, що через відому помилку введення дотиками, на жаль, не може мати ті самі імена дій, що й інші джерела введення.Ви можете створювати п’ять типів тригерів для різних пристроїв:
Окрім п’яти наведених вище типів тригерів, Defold також підтримує введення з акселерометра в нативних застосунках Android та iOS. Установіть прапорець Use Accelerometer у розділі Input вашого файлу game.project.
function on_input(self, action_id, action)
if action.acc_x and action.acc_y and action.acc_z then
-- react to accelerometer data
end
end
Щоб компонент-скрипт або скрипт GUI отримував дії введення, надішліть повідомлення acquire_input_focus ігровому об’єкту, що містить цей компонент:
-- tell the current game object (".") to acquire input focus
msg.post(".", "acquire_input_focus")
Це повідомлення вказує рушію додати до стека введення компоненти ігрового об’єкта, здатні отримувати введення: компоненти-скрипти, компоненти GUI та проксі колекцій (collection proxy). Компоненти ігрового об’єкта розміщуються на вершині стека введення; останній доданий компонент буде на самій вершині. Зауважте: якщо ігровий об’єкт містить кілька компонентів, здатних отримувати введення, до стека буде додано їх усі:

Якщо ігровий об’єкт, що вже отримав фокус введення, отримує його знову, його компонент або компоненти переміщуються на вершину стека.
Дії введення передаються відповідно до стека введення, згори донизу.

Для кожного компонента у стеку, який містить функцію on_input(), ця функція викликається один раз для кожної дії введення протягом кадру з такими аргументами:
selfaction_idnil для руху вказівника й зразків акселерометра. Розрізняйте ці безіменні дії за action.source.actionpressed) тощо. Докладніше про доступні поля дії див. у on_input().function on_input(self, action_id, action)
if action_id == hash("left") and action.pressed then
-- move left
local pos = go.get_position()
pos.x = pos.x - 100
go.set_position(pos)
elseif action_id == hash("right") and action.pressed then
-- move right
local pos = go.get_position()
pos.x = pos.x + 100
go.set_position(pos)
end
end
action.source визначає категорію пристрою введення незалежно від імені дії. Поле доступне у зворотних викликах on_input() скриптів і скриптів GUI та містить один із таких хешів:
action.source |
Категорія введення |
|---|---|
hash("keyboard") |
Окремі натискання клавіш із Key Triggers. |
hash("text") |
Введення тексту й позначеного тексту з Text Triggers, зокрема з фізичної клавіатури. |
hash("mouse") |
Кнопки фізичної миші, коліщатко й рух вказівника. |
hash("touch") |
Дотики, зокрема клацання миші й рух вказівника, імітовані дотиком. |
hash("gamepad") |
Введення геймпада, зокрема необроблені дані й події під’єднання. |
hash("accelerometer") |
Зразки акселерометра. |
Порівнюйте action.source із хешем, наприклад hash("touch"), а не з рядком. Наприклад, дія лівої кнопки миші може надходити як від фізичної миші, так і від дотику. Джерело розрізняє їх навіть під час початкового натискання; див. Як відрізнити клацання миші від дотику.
Коли кілька пристроїв використовують спільну іменовану дію, їхній внесок може об’єднуватися. Джерела обробляються в такому порядку: клавіатура, текст, миша, дотик; повідомляється останнє джерело, що зробило внесок у дію. Відпускання клавіш і кнопок миші зберігає попереднє джерело, якщо в тому самому кадрі немає іншого внеску. Дії геймпадів залишаються окремими для кожного контролера. Використовуйте окремі імена дій, якщо потрібно обробляти кожну прив’язку незалежно.
Рух вказівника й зразки акселерометра не мають імені дії, тому обидва використовують action_id == nil. Вони надходять в окремих зворотних викликах: рух вказівника має координати та джерело миші або дотику, а зразки акселерометра — acc_x, acc_y, acc_z і джерело акселерометра. Якщо обидва виникають в одному кадрі, кожен зворотний виклик можна поглинути незалежно. Зразки акселерометра надходять, навіть якщо їхні значення не змінилися.
Цей приклад обробляє такі безіменні дії. Налаштуйте принаймні один Mouse Trigger для отримання руху вказівника й увімкніть Use Accelerometer на підтримуваному пристрої для отримання зразків акселерометра:
function init(self)
msg.post(".", "acquire_input_focus")
end
function on_input(self, action_id, action)
if action_id == nil then
if action.source == hash("mouse") or action.source == hash("touch") then
print("Pointer position:", action.x, action.y)
elseif action.source == hash("accelerometer") then
print("Acceleration:", action.acc_x, action.acc_y, action.acc_z)
end
end
end
Кожен ігровий світ, динамічно завантажений через проксі колекції, має власний стек введення. Щоб дії досягали стека введення завантаженого світу, компонент проксі має бути у стеку введення головного світу. Усі компоненти у стеку завантаженого світу обробляються до того, як передавання продовжиться вниз головним стеком:

Поширена помилка — забути надіслати acquire_input_focus ігровому об’єкту, що містить компонент проксі колекції. Якщо пропустити цей крок, введення не досягне жодного з компонентів у стеку введення завантаженого світу.
Щоб припинити отримувати дії введення, надішліть ігровому об’єкту повідомлення release_input_focus. Це повідомлення вилучить усі компоненти ігрового об’єкта зі стека введення:
-- tell the current game object (".") to release input focus.
msg.post(".", "release_input_focus")
Функція on_input() компонента може безпосередньо керувати тим, чи слід передавати дії далі вниз стеком:
on_input() повертає false або оператор повернення пропущено (це означає повернення nil, яке в Lua вважається хибним значенням), дії введення передаватимуться наступному компоненту у стеку введення.on_input() повертає true, введення поглинається. Жоден компонент нижче у стеку введення його не отримає. Зауважте, що це стосується всіх стеків введення. Компонент у стеку світу, завантаженого через проксі, може поглинути введення, через що компоненти в головному стеку його не отримають:
Є багато ситуацій, у яких поглинання введення дає простий і потужний спосіб перемикати введення між різними частинами гри. Наприклад, якщо вам потрібне спливне меню, яке тимчасово буде єдиною частиною гри, що отримує введення:

Меню паузи спочатку приховане (вимкнене), а коли гравець торкається елемента PAUSE на HUD, воно вмикається:
function on_input(self, action_id, action)
if action_id == hash("mouse_press") and action.pressed then
-- Did the player press PAUSE?
local pausenode = gui.get_node("pause")
if gui.pick_node(pausenode, action.x, action.y) then
-- Tell the pause menu to take over.
msg.post("pause_menu", "show")
end
end
end

GUI меню паузи отримує фокус введення й поглинає введення, блокуючи будь-яке введення, що не стосується спливного меню:
function on_message(self, message_id, message, sender)
if message_id == hash("show") then
-- Show the pause menu.
local node = gui.get_node("pause_menu")
gui.set_enabled(node, true)
-- Acquire input.
msg.post(".", "acquire_input_focus")
end
end
function on_input(self, action_id, action)
if action_id == hash("mouse_press") and action.pressed then
-- do things...
local resumenode = gui.get_node("resume")
if gui.pick_node(resumenode, action.x, action.y) then
-- Hide the pause menu
local node = gui.get_node("pause_menu")
gui.set_enabled(node, false)
-- Release input.
msg.post(".", "release_input_focus")
end
end
-- Consume all input. Anything below us on the input stack
-- will never see input until we release input focus.
return true
end