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
所有用户输入都由引擎捕获,并作为操作分派给已获取输入焦点并实现了on_input()
函数的游戏对象中的脚本和GUI脚本组件。本手册解释了如何设置绑定以捕获输入,以及如何创建响应输入的代码。
输入系统使用一组简单而强大的概念,允许您按照适合游戏的方式管理输入。
输入绑定是项目范围的表,允许您指定设备输入在分派到脚本组件和GUI脚本之前如何转换为命名的操作。您可以创建一个新的输入绑定文件,在Assets视图中右键点击一个位置并选择New... ▸ Input Binding。要使引擎使用新文件,请更改game.project中的Game Binding条目。
所有新项目模板都会自动创建一个默认的输入绑定文件,因此通常不需要创建新的绑定文件。默认文件名为”game.input_binding”,可以在项目根目录的”input”文件夹中找到。双击该文件在编辑器中打开:
要创建新绑定,点击相关触发类型部分底部的+按钮。每个条目有两个字段:
jump
。请注意,存在一个已知错误,即触摸输入不幸不能与其他输入具有相同的操作名称。您可以创建五种设备特定的触发器类型:
除了上面列出的五种不同触发器类型外,Defold还在原生Android和iOS应用程序中支持加速度计输入。在game.project文件的Input部分中勾选Use Accelerometer框。
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组件和集合代理)添加到输入栈中。游戏对象组件被放在输入栈的顶部;最后添加的组件将位于栈顶。请注意,如果游戏对象包含多个具有输入功能的组件,所有组件都将被添加到栈中:
如果已经获取输入焦点的游戏对象再次这样做,其组件将被移动到栈顶。
输入操作根据输入栈进行分派,从顶部到底部。
栈上任何包含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
,输入被消耗。输入栈中更下方的任何组件都不会接收到输入。请注意,这适用于所有输入栈。代理加载世界栈上的组件可以消耗输入,阻止主栈上的组件接收输入:有许多很好的用例,其中输入消耗提供了一种简单而强大的方式,在游戏的不同部分之间转移输入。例如,如果您需要一个弹出菜单,暂时是游戏中唯一监听输入的部分:
暂停菜单最初是隐藏的(禁用的),当玩家触摸”PAUSE” HUD项时,它被启用:
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
暂停菜单GUI获取输入焦点并消耗输入,防止除弹出菜单相关之外的任何输入:
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