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
Весь пользовательский ввод перехватывается движком и передается в виде действий скпритам и GUI-скриптам в игровых объектах, которые получили фокус ввода и реализуют функцию on_input()
. В этом руководстве объясняется, как настроить привязки для перехвата ввода и как создать код, реагирующий на него.
Система ввода использует набор простых и мощных концепций, позволяя вам управлять вводом так, как вы считаете нужным для вашей игры.
Привязки ввода - это таблица в масштабе проекта, которая позволяет указать, как ввод устройства должен преобразовываться в именованные actions, прежде чем они будут отправлены компонентам скрипта и GUI-скрипта. Вы можете создать новый файл привязки ввода, щелкнув правой кнопкой в Assets и выбрав New... ▸ Input Binding. Чтобы движок использовал новый файл, измените запись Game Binding в game.project.
Файл привязки ввода по умолчанию автоматически создается во всех новых шаблонах проектов, поэтому обычно нет необходимости создавать новый файл привязки. Файл по умолчанию называется “game.input_binding” и находится в папке “input” в корне проекта. Двойной щелчок на файле откроет его в редакторе:
Чтобы создать новую привязку, нажмите кнопку + в нижней части соответствующего раздела типа триггера. Каждая запись имеет два поля:
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
-- реагируем на данные акселерометра
end
end
Чтобы прослушивать действия ввода в компоненте скрипта или GUI-скрипта, сообщение acquire_input_focus
должно быть отправлено игровому объекту, содержащему компонент:
-- сообщаем текущему игровому объекту ("."), чтобы он получил фокус ввода
msg.post(".", "acquire_input_focus")
Это сообщение инструктирует движок добавить компоненты с возможностью ввода (компоненты сценария, компоненты GUI и прокси коллекции) в игровых объектах в стек ввода. Компоненты игрового объекта помещаются на вершину стека ввода; компонент, добавленный последним, будет находиться на вершине стека. Обратите внимание, что если игровой объект содержит более одного компонента с возможностью ввода, все компоненты будут добавлены в стек:
IЕсли игровой объект, который уже получил фокус ввода, делает это снова, его компонент(ы) перемещается(ются) на вершину стека.
Действия ввода отправляются в соответствии со стеком ввода данных, сверху вниз.
У любого компонента, который находится в стеке, содержащем функцию on_input()
, эта функция будет вызываться, один раз для каждого действия ввода в течение кадра, со следующими аргументами:
self
action_id
action
нажата
и т.д. Подробности о доступных полях действия см. в on_input().function on_input(self, action_id, action)
if action_id == hash("left") and action.pressed then
-- сдвигаемся влево
local pos = go.get_position()
pos.x = pos.x - 100
go.set_position(pos)
elseif action_id == hash("right") and action.pressed then
-- сдвигаемся вправо
local pos = go.get_position()
pos.x = pos.x + 100
go.set_position(pos)
end
end
Каждый игровой мир, динамически загружаемый через прокси-коллекцию, имеет свой собственный стек ввода. Чтобы отправка действий достигла стека ввода загруженного мира, доверенный компонент должен находиться в стеке ввода основного мира. Все компоненты в стеке загруженного мира обрабатываются до того, как отправка продолжится в главном стеке:
Частая ошибка - забыть отправить acquire_input_focus
игровому объекту, содержащему компонент прокси-коллекции. Пропуск этого шага не позволяет вводу достичь любого из компонентов в стеке ввода загруженного мира.
Чтобы прекратить прослушивание действий ввода, отправьте игровому объекту сообщение release_input_focus
. Это сообщение удалит все компоненты игрового объекта из стека ввода:
-- сообщим текущему игровому объекту ("."), чтобы он освободил фокус ввода.
msg.post(".", "release_input_focus")
Компонент on_input()
может активно контролировать, следует ли передавать действия дальше по стеку или нет:
on_input()
возвращает false
, или возврат пропущен (это подразумевает возврат nil
, который является ложным значением в Lua), действия ввода будут переданы следующему компоненту на стеке ввода.on_input()
возвращает true
, ввод обрабатывается. Ни один компонент, расположенный ниже по стеку ввода, не получит данные ввода. Обратите внимание, что это относится ко всем стекам ввода. Компонент на стеке прокси-загруженного мира может обрабатывать ввод, не позволяя компонентам на основном стеке получать ввод:Есть много хороших примеров использования, когда обработка ввода обеспечивает простой и мощный способ переключения ввода между различными частями игры. Например, если вам нужно всплывающее меню, которое временно является единственной частью игры, которая прослушивает ввод:
Меню паузы изначально скрыто (отключено), а когда игрок касается элемента HUD “PAUSE”, оно включается:
function on_input(self, action_id, action)
if action_id == hash("mouse_press") and action.pressed then
-- Проверяем, нажал ли игрок кнопку PAUSE?
local pausenode = gui.get_node("pause")
if gui.pick_node(pausenode, action.x, action.y) then
-- Отображаем меню паузы
msg.post("pause_menu", "show")
end
end
end
Меню паузы получает фокус ввода и ввод, предотвращая любой другой ввод, кроме того, который относится к всплывающему меню:
function on_message(self, message_id, message, sender)
if message_id == hash("show") then
-- Отображаем меню паузы.
local node = gui.get_node("pause_menu")
gui.set_enabled(node, true)
-- Получаем данные ввода.
msg.post(".", "acquire_input_focus")
end
end
function on_input(self, action_id, action)
if action_id == hash("mouse_press") and action.pressed then
-- делаем что-нибудь...
local resumenode = gui.get_node("resume")
if gui.pick_node(resumenode, action.x, action.y) then
-- Скрываем меню паузы
local node = gui.get_node("pause_menu")
gui.set_enabled(node, false)
-- Освобождаем ввод.
msg.post(".", "release_input_focus")
end
end
-- Обрабатывеам все входные данные. Все, что находится ниже в стеке ввода
-- никогда не увидит данные ввода, пока мы не освободим фокус ввода.
return true
end
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB