触摸控制
触摸控制从DDNet客户端的18.8版本后已经可用,这也是近期首个发布的DDNet安卓版。早期的安卓版DDNet为9.3.1版本,此版本有一个单独的教程。以下教程只考虑18.8以及更新版本的触摸控制。
用户界面可通过触摸控制进行的操作如下:
- 在任意地方触摸可移动光标或进行一次鼠标左键点击。
- 在几乎一个地点按住至少0.5秒可进行一次鼠标右键点击。
- 用两根手指可向上或下滚动可滚动条,例如服务器浏览器和控制台。
- 在安卓上:用(虚拟)返回键当做退出键,可关闭菜单等。
在游戏中的触摸控制可以用配置变量cl_touch_controls
来开启/关闭,此变量在安卓默认为1
,在其他平台则是0
。触摸控制应该在其他支持触摸功能的平台上也能使用,但是此教程主要在安卓上进行的测试。
游戏内触摸控制包含多种在屏幕上的按键。不同按键仅会在特定时候显示,取决于其内容。例如移动键仅会在游玩过程中显示。
默认键位
左,右移动键以及跳跃键的布局类似于⊥
的样子,和WASD控制类似。
对于开火和出钩动作,这里设置了两种模式:
- 直接的点击输入:准星会直接移动至玩家点击屏幕的位置。
- 虚拟摇杆:一个按键会模拟摇杆,可以使准星相对于屏幕中心移动。
在两个模式中,一个按键可用于切换当前启用的动作(开火和出钩)。当虚拟摇杆被按下时,该按键可以直接使用未被启用的动作而不是切换。
直接点击输入模式可以依据在游戏内/旁观中分别调整功能,以此在使用摇杆时避免不必要的点击输入。
旁观时,直接点击输入可用于移动地图,类似于在图片/地图预览器。虚拟摇杆也可用于在旁观时移动地图。
两个独立的按钮可分别用于切换至上一个或下一个武器。
一个汉堡包菜单按钮☰
可用于切换更少使用按键的可见性,包括显示记分板,显示表情选择器,显示旁观菜单,打开队伍和队伍内聊天,投票赞成/反对,和缩放按键。长按汉堡包菜单按钮会打开游戏内菜单。
当分身被连接时,一个用于切换分身和本体的按键会显示。
表情选择器和旁观菜单可被相关按键打开,之后可通过在面板外点击或使用返回键关闭,另外仅当相关按钮被按下时才打开面板这种设置目前而言不可行,至少这种设置对于旁观菜单而言不便利。
键位设置格式
上述提到的默认键位是在一个名为touch_controls.json
的文件中被加载,该文件位于data
目录因此无法被修改。该键位可通过在配置目录中创建一个名为touch_controls.json
来修改。
键位配置文件是一个JSON格式的文本文件。推荐先学习JSON的基本格式来更好的理解以下教程。配置文件必须是一个有效的JSON文件。JSON格式的教程和检查工具可在网络上找到。JSON文件的结构如下。
JSON文件的根元素必须是一个对象。该对象的属性"touch-buttons"
可定义一系列按键的对象。每一个按键对象有以下可调节的性质:
- 位置和大小 (属性
"x"
,"y"
,"w"
,"h"
):横/纵坐标和宽/高数据为在单位长度为1000000²的表格上的整数。这些单位表格数据会在游戏内依据屏幕大小和纵横比转换为屏幕表格数据。这意味着当分辨率改变时一些按键可能会表现得被伸展,但这也使我们对于不同的屏幕纵横比可提供一个合理的默认值 - 形状 (属性
"shape"
):决定显示出来的按键形状。"rect"
:方形。"circle"
:圆形。该按键大小会被自动调整,从而使宽度和高度一致。
- 可见度 (属性
"visibilities"
):一系列预置的可见度设置可供选择,且仅当所有情况都满足时该按键才会显示。若可见度置空则代表该按键总是显示。预置有以下设置:"ingame"
:玩家在游戏中,即没有在旁观。"extra-menu"
,"extra-menu-2"
,"extra-menu-3"
,"extra-menu-4"
,"extra-menu-5"
: 给定数字对应的附加菜单处于打开状态。"zoom-allowed"
: 该服务器允许缩放。"vote-active"
: 正在进行投票。"dummy-allowed"
: 该服务器允许分身。"dummy-connected"
: 分身已经被连接。"rcon-authed"
: 玩家登录了管理员账号。"demo-player"
: 正位于录像播放器。- 所有可见度都可以在前面添加
-
来实现反转。例如:"-ingame"
仅在玩家未处于游戏中时满足,即旁观中。
- 行为 (属性
"behavior"
):一个定义此按键按下/松开时执行的动作的对象,也包括其标签。属性"type"
用于区分使用的行为种类。行为种类只能是预设(硬编码的),或者基于通用的控制台指令(类似于绑定)。预设的行为仅在需要时才使用,除此之外所有按键为通用绑定。- 预设行为 (属性
"type"
被设置为"predefined"
):属性"id"
被设置为一个固定的字符串,以此确认使用的预设行为。以下为可用的预设行为:"ingame-menu"
: 松开该按钮时直接打开游戏菜单。"extra-menu"
: 附加菜单按钮,切换带有"extra-menu"
,"extra-menu-2"
,"extra-menu-3"
,"extra-menu-4"
和"extra-menu-5"
可见度的按钮的可见度。按住一段时间后松手则会打开游戏菜单。- 给属性
"number"
定义一个在1至5之间的整数即可对应相应的可见度"extra-menu"
,"extra-menu-2"
,"extra-menu-3"
,"extra-menu-4"
,"extra-menu-5"
。
- 给属性
"emoticon"
: 打开表情选择器(此功能无法通过绑定使用)。"spectate"
: 打开旁观菜单(此功能无法通过绑定使用)。"swap-action"
:切换当前激活的由直接点击和虚拟摇杆执行的动作(开火和出钩)。"use-action"
:以当前瞄准角度执行激活的动作。"joystick-action"
:使用当前激活动作的虚拟摇杆 。"joystick-aim"
:仅提供瞄准的虚拟摇杆,不会执行其他动作。"joystick-fire"
:总是会执行开火的虚拟摇杆。"joystick-hook"
: 总是会执行出钩的虚拟摇杆。
- 绑定行为(属性
"type"
设置为"bind"
)。带此行为的按键会执行控制台命令,和常规绑定类似。- 属性
"label"
定义一个字符串作为该按键的标签。 - 属性
"label-type"
被定义为一个字符串来决定该按键的标签种类,即属性"label"
的处理方法:"plain"
: 该标签会被直接使用,不会做出任何改变。"localized"
: 标签会被自动翻译。仅在有对应翻译时可用。"icon"
: 图标字体被用于该标签。图标必须为UTF-16编码,使用\uXXXX
。例如\uf3ce
为手机图标,Unicode为f3ce
。注意该图标必须在Font Awesome Free可用。
- 属性
"command"
被定义为一个可以在控制台运行的指令类型字符串,类似于绑定。例如"+fire"
为开火动作。
- 属性
- 绑定切换行为(属性
type
设置为"bind-toggle"
)。带此行为的按键会在两个及以上的指令之间循环触发。- 属性
"commands"
定义了两个及以上的指令,依据先后排列顺序依次触发。每个指令为一个带属性"label"
,"label-type"
和"command"
的对象,与上述绑定行为的定义一致。在该组中必须至少定义两个指令对象。
- 属性
- 预设行为 (属性
除此之外,根对象还有以下属性:
"direct-touch-ingame"
: 定义在游戏中直接点击所执行的动作。可用的值有:"disabled"
:游戏中直接点击不会执行任何动作。这意味着需要使用虚拟摇杆。"action"
:直接点击会使用当前被激活的动作(见上)。"aim"
:直接点击仅会改变瞄准角度,不会执行其他动作。这意味着你需要其他按钮来开火或出钩。"fire"
:直接点击总是会开火。"hook"
:直接点击总是会出钩。
"direct-touch-spectate"
:定义在旁观时直接点击所执行的动作。可用的值有:"disabled"
:旁观时直接点击不会执行任何动作。这意味着需要使用虚拟摇杆。"aim"
:直接点击可用于旁观。
游戏内菜单
除了屏幕上的触摸控制,当cl_touch_controls
被开启时,在游戏内菜单会出现第二行不太常用,但没有键盘则无法使用的功能:
- 开启本地和远程控制台的按键。不用自定义按键打开控制台可以在键位导入失败时便捷地查看控制台内的错误信息。
- 关闭菜单的按键,在虚拟返回键未显示时使关闭菜单更方便。
- 打开键位编辑器的选项(见下)。
键位编辑器
键位编辑器在被启用时会显示在游戏内菜单的主屏幕上。该编辑器目前只有最基本的键位编辑功能。
- 保存当前设置至配置目录中的
touch_controls.json
文件。 - 取消当前设置,并加载配置目录中的
touch_controls.json
文件。 - 加载数据目录中的
touch_controls.json
文件从而将键位初始化。 - 用于提醒当前设置未被保存。
- 从剪贴板导入设置,或将设置导出至剪贴板。在较新的安卓版本中这是修改键位的唯一方法,因为无法直接修改应用的数据。
同时,全局的触摸控制也可以在该界面被修改:
- 游戏中和旁观时的直接点击输入(见键位设置格式)可以用下拉菜单调整。
当键位编辑器被打开时,所有按键都会无条件显示,从而让玩家更好地排列按键。
调整键位
- 导出当前键位至剪贴板。
- 将剪贴板内容粘贴至一个文件来修改它。同时你也应该给你的键位设置备份!
- 修改键位设置(关于相关格式见上)。
- 复制所有内容至剪贴板,然后在客户端内导入。若导入失败,在本地控制台内找到包含
touch_controls
的错误消息,并更正错误。用在线工具可更正JSON文本的错误和格式化。 - 更改完成后在客户端中保存你的设置。你也可撤销更改或者初始化键位如果你搞砸了。
一个可在客户端内直接修改键位的界面在计划中。
注:你也可直接更改配置目录中的touch_controls.json
文件来修改键位,而不是导出/导入到剪贴板,但在安卓该做法不可行。
示例
全局键位格式设置的示例:
{
"direct-touch-ingame": "action",
"direct-touch-spectate": "aim",
"touch-buttons": [
...
]
}
示例按钮,带有"bind"
的行为,会在对话框返回一条消息:
{
"x": 500000,
"y": 500000,
"w": 100000,
"h": 100000,
"shape": "rect",
"visibilities": [
],
"behavior": {
"type": "bind",
"label": "Example",
"label-type": "plain",
"command": "echo Hello world!"
}
}
示例按钮,带有"predefined"
的行为,是一个会执行当前被激活的行为的虚拟摇杆:
{
"x": 755000,
"y": 580000,
"w": 225000,
"h": 400000,
"shape": "circle",
"visibilities": [
"ingame"
],
"behavior": {
"type": "predefined",
"id": "joystick-action"
}
}
示例按钮,带有"bind-toggle"
的行为,会在对话框循环返回三条不同的消息:
{
"x": 600000,
"y": 200000,
"w": 100000,
"h": 100000,
"shape": "rect",
"visibilities": [
],
"behavior": {
"type": "bind-toggle",
"commands": [
{
"label": "Echo 1",
"label-type": "plain",
"command": "echo 1"
},
{
"label": "Echo 2",
"label-type": "plain",
"command": "echo 2"
},
{
"label": "Echo 3",
"label-type": "plain",
"command": "echo 3"
}
]
}
}
已知的问题
- 安卓的问题:同时按下三根手指会导致所有手指被立即同时松开。
- 解决方法:原因是你手机自带的全局多指手势动作(设置里面搜"三指")。具体地,关闭"三指下滑截屏","三指长按截屏","三指上滑进入菜单"功能。
- 安卓的问题:有时候点击屏幕顶端15%位置会无响应或响应不连续。
- 解决方法:目前不清楚原因。一般可以重启应用,返回手机主界面也可能可以修复该问题。
实现细则
以下为实现触摸控制的细节,为开发者准备。
游戏内触摸控制在单独的客户端组件CTouchControls
中实现,该组件位于src/game/client/components/touch_controls.cpp
和
src/game/client/components/touch_concontrol.h
文件中。尽量直接使用绑定作为按钮的行为而不是预定义行为,从而降低复杂度。
在分叉客户端中加入你自己的按键行为时,建议在新形状,可见性,行为等前加上你的分叉的名称。例如:
myfork.octagon
如果你添加一个八边形的按键,从而避免和未来的版本发生冲突。
为其他的客户端组件例如表情轮盘和旁观菜单添加触摸控制支持时,使用
CUi::UpdateTouchState
函数。确保你的组件会在接收KEY_ESCAPE
时自动关闭,即安卓上的返回键。注意在每一帧中,只有一个组件可以使用触摸状态,因此按住一个游戏按键时同时用另一个手指使用另一个组件例如表情轮盘是不可能的。相反,相应的预定义按钮触摸行为(例如CSpectateTouchButtonBehavior
)仅会触发游戏内的组件(例如旁观菜单),但是不会将其再次停用。激活OnActivate
函数中的组件已经会导致激活按钮的手指同时会影响激活的组件。
参考
- 默认的键位文件:https://github.com/ddnet/ddnet/blob/84b1c3c49c8d97a6911da34424d2023879ccdaf8/data/touch_controls.json
- 向用户界面和引擎中添加触摸控制的拉取请求:https://github.com/ddnet/ddnet/pull/8621
- 添加游戏内触摸控制的拉取请求:https://github.com/ddnet/ddnet/pull/8632
- 添加表情选择器和旁观菜单的拉取请求:https://github.com/ddnet/ddnet/pull/8801