觸屏操控
觸屏操控從DDNet 18.8版本客戶端開始啟用,這也標誌著最近期的首個DDNet安卓版發布。早期的安卓版本為DDNet 9.3.1,該版本已有一個單獨教程。以下教程將只考慮18.8以後版本的觸屏操控。
在用戶界面可以進行的觸屏操控如下:
- 直接點擊屏幕某位置:視為移動光標至該位置並用左鍵單擊;
- 長按屏幕某位置至少0.5秒:視為用滑鼠右鍵單擊該位置,輕微移動手指不影響判定;
- 用兩根手指長按屏幕並上下滑動:視為在該位置滾動滑鼠滾輪,可以上下滾動列表如伺服器瀏覽器和控制台;
- 在安卓設備上觸發了(虛擬)返回鍵:視為使用了Esc鍵,可關閉菜單等。
在遊戲界面內的觸屏操控可以通過配置參數cl_touch_controls
來開啟/關閉,此參數在安卓設備上默認為1
,在其他平台則是0
。觸屏操控在其他支持觸控的平台上應該也能正常使用,但此教程主要針對安卓設備進行測試。
遊戲內觸屏操控包含許多屏幕按鈕。不同按鈕根據功能不同僅會在可用時顯示,例如移動鍵僅會在進行遊玩時顯示。
默認觸控按鍵配置

左、右移動和跳躍鍵的位置分布形如⊥
,和鍵盤上的WASD分布類似。
關於開火和出鉤的操作,遊戲內默認提供了兩種操作方式:
- 通過直接點擊屏幕空白處,可以將準星直接移動到點擊處並立即朝準星處開火或出鉤,此時不鬆手拖動可以控制瞄準角度或不松鉤;
- 通過拖動虛擬搖杆按鈕,可以將準星以玩家位置為原點朝拖動方向移動,同時開火或出鉤。
在兩種操作方式下都可以點擊右上角的「當前」功能按鈕切換為開火或出鉤模式。當按住虛擬搖杆時,「當前」按鈕將變成直接觸發另一功能的按鈕,按鈕上的文字提示也會相應改變。
對於遊戲或旁觀時,可以分別設置直接點擊屏幕的功能,通過禁用「直接觸摸操作」可以避免遊戲中使用搖杆的同時點擊誤觸。
旁觀模式下,如果將直接觸屏操控設置為瞄準,則可以類似圖片一樣拖動地圖進行觀察;如果設置為禁用,則只能在搖杆範圍內拖動。
默認情況下左上角有兩個按鈕用於切換上一武器和下一武器。

左上角的☰
字形按鈕是遊戲內菜單按鈕,可用於顯示或隱藏更多按鈕,這些按鈕大部分與遊戲操作無關。包括顯示計分板、表情輪盤、旁觀列表、全局聊天、隊伍內聊天的按鈕,以及投票按鈕和視野縮放按鈕。長按菜單按鈕鬆手時會打開類似於電腦按下 Esc 後的遊戲內菜單,當然安卓設備也可以使用返回鍵代替。
連接分身後,右上角會出現切換分身的按鈕。
顯示更多按鈕時,可以打開表情輪盤或旁觀列表等菜單,點擊表情發送或點擊旁觀對象觀察,點擊空白處則可以關閉菜單,安卓設備可以使用返回鍵關閉。但是目前還無法實現長按按鈕時顯示菜單、鬆手自動關閉的功能,並且也不適合用於旁觀列表。
自定義觸控鍵位設置
默認鍵位保存在touch_controls.json
文件中,安卓版本下該文件位於data
目錄,高版本安卓設備一般會禁止用戶修改這一目錄下的文件。因此如果您要進行鍵位自定義,需要通過在配置目錄中創建同名為touch_controls.json
的文件,利用更高的優先度來覆蓋默認設置。
鍵位配置文件是JSON格式的文本文件,推薦在掌握一定JSON基礎的情況下閱讀下方教程,在配置JSON文件時必須保證有效性。關於JSON格式的相關教程和工具可在網絡上找到,下面也會涉及到許多相關術語,當然也可以將遊戲配置文件當作練習對象來學習JSON,但是建議在進行實操前先做好重要文件的備份。本教程涉及的JSON配置文件的結構如下:
JSON文件的根元素必須是一個對象。該對象的屬性"touch-buttons"
可定義一系列按鈕對象。按鈕對象都可調節下列屬性:
- 位置和大小(屬性
"x"
,"y"
,"w"
,"h"
):屏幕顯示區域將被平均劃分為1000000x1000000的網格,前面提到的四個屬性為整數,大小分別表示按鈕的中心點橫縱坐標和寬度高度。網格的實際單位長度會根據遊戲窗口大小及屏幕比例實時拉伸,因此對於不同的屏幕設備,只要屏幕縱橫比差異不大,按鈕布局就不會變得特別不合理。 - 形狀 (屬性
"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
。注意該圖標必須來自於DDNet或在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
設置為 1 (推薦值)後,在菜單欄下方第二行還會出現一些不常用但重要又需要鍵盤才能使用的功能:
- 打開本地和遠程控制台的按鈕:當綁定控制台開關的觸控按鍵失效時,仍可以快捷查看顯示在控制台的錯誤信息;
- 菜單關閉按鈕:在不方便使用返回鍵時更便於關閉菜單。
- 鍵位編輯器開關(詳情見下方)。
觸控編輯器

觸控編輯器在被啟用後會在遊戲菜單欄的主屏幕上顯示,目前只有如下有限的觸控設置管理功能:
- 保存更改:將當前觸控設置保存到配置目錄下的
touch_controls.json
文件中; - 放棄更改:撤銷當前對觸控設置的改變,並重新加載配置目錄下的
touch_controls.json
文件; - 恢復默認設置:從數據目錄中加載
touch_controls.json
文件來將鍵位初始化; - 右上角留白用於提醒當前是否有設置未被保存;
- 從剪貼板導入設置,或將設置導出至剪貼板。在較新的安卓版本中應用數據無法直接修改,因此導入寫好的設置文件是修改鍵位的唯一方法。
另外,對屏幕空白處進行操作的模式也可以在該界面被修改:
- 「直接觸摸操作」下拉菜單調整的正是上方提及的遊戲模式參數
direct-touch-ingame
和旁觀模式參數direct-touch-spectate
(參見上方,自定義觸控鍵位設置)。
當觸控編輯器打開時,所有按鈕無視可見性屬性並全部顯示,從而讓玩家更易觀察和調整按鍵位置。
鍵位調整
- 導出當前鍵位至剪貼板。
- 將剪貼板內容保存為文件便於進行修改。請記得給您的鍵位設置留下備份!
- 修改鍵位設置(相關格式細節請參見上方)。
- 複製編輯好的內容至剪貼板,然後導入到客戶端。若導入失敗,在本地控制台內找到包含
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
文件中。如果一些按鈕的功能可以直接通過綁定實現,儘量不要增加預設行為讓代碼變複雜。
當您想在分叉客戶端中添加自己的按鍵行為時,建議在新增的形狀、可見性和行為等等之前加上您的分叉的名稱。例如:用 您的分叉.octagon
來表示您添加的八邊形按鍵,預防與未來的版本更新發生衝突。
為其他的遊戲內客戶端組件例如表情輪盤和旁觀菜單添加觸屏操控支持時,請使用CUi::UpdateTouchState
這一觸摸狀態監測函數。
確保您的組件能在接收到KEY_ESCAPE
信號時立即關閉,即安卓上的返回鍵。
注意在每一遊戲幀中,只能有一個組件可以響應觸摸狀態,因此在占用遊戲內觸控組件的同時無法使用另一個組件的內容,例如按住一個遊戲內按鈕就無法使用表情輪盤。
然而,按鈕的預設行為(例如CSpectateTouchButtonBehavior
)在調用OnDeactivate
函數打開遊戲內的組件(例如旁觀菜單)之後不會禁用它,此時手指按下會同時影響按鈕和它打開的組件。
參考資料
- 默認鍵位配置文件: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