触控操作
DDNet 移动端触控操作的详细指南,包括默认配置、自定义按钮配置和触摸控制编辑器的使用方法
来源: https://wiki.ddnet.org/wiki/Touch controls
触摸控制自 DDNet 客户端 18.8 版本起可用,该版本也是客户端首次在 Android 上发布的版本。
基本操作
用户界面可以通过触摸控制使用,如下所示:
- 触摸任意位置:移动光标并执行左键点击
- 触摸并保持至少 0.5 秒:执行右键点击
- 使用两根手指:在可滚动列表(如服务器浏览器和控制台)中上下滚动
- Android 返回按钮:像 Escape 键一样关闭菜单等
游戏内触摸控制可以通过配置变量 cl_touch_controls 启用/禁用,该变量在 Android 上默认为 1,在其他平台上默认为 0。触摸控制也应该在其他支持触摸设备的平台上工作,但本指南主要在 Android 上进行了测试。
游戏内触摸控制由各种屏幕触摸按钮组成。不同的按钮仅在根据上下文可用时才显示,例如移动按钮仅在游戏内显示。
默认触摸按钮配置
图片加载失败
左、右和跳跃动作的移动按钮以类似 WASD 控制的 ⊥ 形排列。
开火和钩子动作模式
对于开火和钩子动作,实现了两种模式:
- 直接触摸输入:鼠标精确移动到玩家在屏幕上触摸的位置
- 虚拟摇杆:使用按钮模拟摇杆,相对于屏幕中心移动鼠标
在任一模式下,使用一个按钮在活动动作(开火和钩子)之间切换。当按住虚拟摇杆时,此按钮直接使用另一个动作而不是切换它。
直接触摸输入模式可以分别为游戏内/观战调整,以防止在使用摇杆时意外直接触摸输入。
观战时,使用直接触摸输入可以直接平移地图,就像在图像/地图查看器中一样。观战时也可以使用虚拟摇杆平移地图。
显示两个单独的按钮用于切换到上一个和下一个武器。
图片加载失败
汉堡菜单
汉堡菜单按钮 ☰ 用于切换较少使用的触摸按钮的可见性。这包括:
- 显示计分板
- 显示表情选择器
- 显示观战菜单
- 打开队伍和队伍聊天
- 投票是/否
- 缩放
长按汉堡菜单按钮将打开游戏内菜单。
当 dummy 连接时,显示一个用于在主体和 dummy 之间切换的按钮。
表情选择器和观战菜单通过相应的触摸按钮激活,可以通过触摸它们外部或使用返回按钮来停用,因为在按住游戏内触摸按钮时切换它们目前不可行,而且至少对于使用观战菜单来说也不方便。
触摸按钮配置格式
上述默认按钮布局从 data 目录中的 touch_controls.json 文件加载,不应修改。可以通过在 config 目录中创建 touch_controls.json 文件来覆盖此布局。
触摸按钮配置是 JSON 格式的文本文件。建议先学习 JSON 格式的基础知识以理解以下指南。配置必须是有效的 JSON 文件。互联网上有 JSON 格式的指南和验证工具。
JSON 文件结构
JSON 文件中的根元素必须是对象。根对象的 "touch-buttons" 属性指定触摸按钮对象的数组。
每个触摸按钮对象的属性
位置和大小
属性 "x"、"y"、"w"、"h":
- X/Y 位置和宽度/高度是 1,000,000² 网格上的整数
- 这些单位网格值在运行时根据屏幕的大小和宽高比转换为屏幕网格值
- 这意味着如果分辨率改变,按钮可能会显示拉伸,但它允许我们为略有不同的宽高比提供合理的默认值
形状
属性 "shape":确定渲染的按钮形状
可见性
属性 "visibilities":可以选择一组预定义的可见性类,只有当所有条件都满足时才显示按钮。空数组表示按钮始终显示。
注意:所有可见性类都可以通过前缀
-来反转,例如"-ingame"在玩家不在游戏中(即观战)时满足。
行为
属性 "behavior":描述此触摸按钮在激活/停用时的行为及其标签的对象。
属性 "type" 用于区分使用哪种类型的行为。行为要么是预定义的(硬编码),要么基于通用控制台命令(如绑定)。预定义行为仅在必要时使用,所有其他按钮表示为通用绑定。
预定义行为
属性 "type" 设置为 "predefined",属性 "id" 设置为固定字符串值:
extra-menu 属性:属性
"number"指定 1 到 5 之间的整数,将此按钮与相应的可见性关联。如果未给出"number",将自动设置为1。
绑定行为
属性 "type" 设置为 "bind":
label-type 值:
绑定切换行为
属性 type 设置为 "bind-toggle":
- 具有此行为的按钮在执行两个或更多指定命令之一之间循环
- 属性
"commands"按显示和执行的顺序指定两个或更多命令的数组 - 每个命令是一个具有属性
"label"、"label-type"和"command"的对象 - 数组中必须至少指定两个命令对象
根对象的其他属性
直接触摸输入模式
"direct-touch-ingame" 可能的值:
"direct-touch-spectate" 可能的值:
颜色格式
颜色指定为十六进制字符串,格式为 RRGGBBAA、RRGGBB、RGBA 和 RGB,不带任何前缀如 #,例如 "A526C440"。如果省略 alpha 值,则默认设置为完全不透明。
游戏内菜单按钮

除了独立的屏幕触摸控制外,当启用 cl_touch_controls 时,游戏内菜单主页会添加第二行,用于显示没有键盘无法使用的较少使用功能:
- 打开本地和远程控制台的按钮。在不使用触摸控制的情况下打开本地控制台很有用,因为如果无法加载触摸控制配置,错误消息会显示在那里
- 关闭菜单的按钮,如果不总是显示虚拟返回按钮,这更方便
- 用于切换触摸控制编辑器 UI 的复选框(见下文)
游戏内触摸控制编辑器
自 DDNet 客户端 19.4 版本起,还提供了触摸控制的图形编辑器。详细信息和屏幕截图可在 https://github.com/ddnet/ddnet/pull/9965 找到。

启用时,用于调整触摸控制的用户界面渲染在游戏内菜单的主屏幕上。目前,触摸控制编辑器仅限于基本配置管理功能:
- 将配置保存到 config 目录中的
touch_controls.json文件 - 通过从 config 目录重新加载
touch_controls.json文件来放弃当前更改 - 通过从 data 目录重新加载
touch_controls.json文件来恢复默认配置 - 显示是否有未保存的更改
- 从剪贴板导入和导出配置。这是在较新 Android 版本上编辑配置的唯一方法,因为无法再在应用存储中编辑文件
全局触摸控制设置
此外,可以在此 UI 中调整全局触摸控制设置:
- 游戏内和观战时的直接触摸输入模式(见触摸按钮配置格式)可以通过下拉菜单调整
当触摸控制编辑器处于活动状态时,无论可见性如何,都会显示所有触摸按钮,以更好地支持排列按钮。
调整控制步骤
- 将触摸配置导出到剪贴板
- 将剪贴板保存到文件,以便更轻松地编辑。你也应该这样做以备份你的配置!
- 编辑配置(有关格式的详细信息,请参见上文)
- 将编辑后的配置复制到剪贴板并在客户端中再次导入。如果配置无法成功加载,请检查本地控制台中包含
touch_controls的错误消息并相应地修复配置。使用在线工具进行 JSON 验证和格式化 - 完成后在客户端中保存更改。如果你搞砸了,也可以放弃更改或恢复默认值
注意:你也可以直接编辑 config 目录中的
touch_controls.json文件,而不是从/到剪贴板导出/导入,但这在 Android 上不受支持。
示例
触摸配置整体结构示例
{
"direct-touch-ingame": "action",
"direct-touch-spectate": "aim",
"background-color-inactive": "00000040",
"background-color-active": "33333340",
"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"
}
]
}
}已知问题
Android 上的问题:同时按下 3 根或更多手指会导致所有手指立即释放
解决方案:这是由处理多指全局手势的手机功能引起的。打开设置应用并禁用涉及 3 根或更多手指的手势功能(搜索"3 fingers")。特别是,禁用:
- "用 3 根手指向下滑动截图"
- "用 3 根手指触摸并按住截图"
- "用 3 根手指向上滑动进入分屏视图"功能
Android 上的问题:偶尔,在屏幕顶部约 15% 区域触摸根本不起作用或非常不一致
解决方案:目前不清楚是什么原因导致的。重启应用应该可以修复。返回主屏幕也可能修复它。
实现细节
这些是关于触摸控制实现的详细信息,供开发者参考。
游戏内触摸控制在单独的客户端组件 CTouchControls 中实现,位于文件 src/game/client/components/touch_controls.cpp 和 src/game/client/components/touch_controls.h 中。只要可能,直接使用绑定作为按钮行为而不是使用预定义行为以降低复杂性。
在分叉客户端中添加自己的按钮行为时,建议使用分叉名称作为新形状、可见性、行为等名称的前缀,例如,如果你为八角形按钮添加新形状,使用 myfork.octagon,以防止未来版本中的冲突。
要为其他游戏内客户端组件(如表情轮盘和观战菜单)添加触摸支持,请使用 CUi::UpdateTouchState 函数,就像表情轮盘和观战菜单一样。确保你的组件处理 KEY_ESCAPE 以关闭自身,这也对应于 Android 上的返回按钮。请注意,每帧只有一个组件可以使用触摸状态,因此无法在按住游戏内触摸按钮的同时用其他手指使用表情轮盘等其他组件。相反,相应的预定义触摸按钮行为(例如 CSpectateTouchButtonBehavior)仅在其 OnDeactivate 函数中激活游戏内组件(例如观战菜单),但不会再次停用它。在 OnActivate 函数中激活组件会导致激活按钮的手指也影响激活的组件。
参考资料
- 默认触摸按钮配置:https://github.com/ddnet/ddnet/blob/69c92a79e6bab9f9390245f518c5340222c544dc/data/touch_controls.json
- 将触摸控制添加到引擎和 UI 的 Pull Request:https://github.com/ddnet/ddnet/pull/8621
- 添加游戏内触摸控制的 Pull Request:https://github.com/ddnet/ddnet/pull/8632
- 添加表情和观战触摸控制的 Pull Request:https://github.com/ddnet/ddnet/pull/8801
- 添加触摸控制编辑器的 Pull Request:https://github.com/ddnet/ddnet/pull/9965
小提示
- 基本操作:触摸移动光标,长按右键,双指滚动
- 配置变量:
cl_touch_controls启用/禁用触摸控制 - 默认布局:移动按钮呈
⊥形,支持直接触摸和虚拟摇杆两种模式 - 汉堡菜单:
☰按钮切换额外功能,长按打开游戏内菜单 - 自定义配置:在 config 目录创建
touch_controls.json覆盖默认配置 - 编辑器:DDNet 19.4+ 提供图形化触摸控制编辑器
- Android 问题:禁用 3 指手势解决多指冲突问题