一、專案資訊
專案名稱: GameAgent
專案簡介: 一個 Windows 上的遊戲/模擬器自動化工具。用截圖比對找到畫面上的按鈕後點擊,並用一套自訂的文字指令語言(DSL)把操作串成腳本。目標是把「每天登入、領獎勵、刷日常」這類重複操作交給程式。
開發狀態: 已發布 v2.3,持續更新中。v2 將 Core 與 UI 拆開,並修正了 v1 的圖片等待與執行問題。
二、必要連結
GitHub: https://github.com/b200077/gameAgent
三、技術實作內容
我同時玩好幾款手遊,每天的日常流程幾乎一樣:開遊戲、等載入、點掉公告、領獎勵、進副本。市面上的連點器只能記錄座標,遇到載入時間不固定、彈窗位置改變就會點錯。我想要的是「看到某個畫面才執行下一步」,並且能像寫文字一樣編輯流程。
指令檔的格式如下:
日常:{開啟遊戲, waitImg->登入畫面, 公告關閉?, callcommand:領獎勵}
領獎勵:{信箱, 全部領取✓, 關閉}
步驟可以是圖片名稱、wait3、press->esc、"文字輸入"、條件式(week-Sun->某指令),也可以把別的指令當模組呼叫。
挑戰 A:為什麼 UI 與 Core 要拆成兩個行程?
操作遊戲視窗有時需要管理員權限,但我不想讓整個 UI 都以管理員執行。另外 Core 常駐背景、UI 隨開隨關,兩者生命週期本來就不同。v1 兩者合在一起,圖片等待和執行時常互相卡住。
挑戰 B:腳本執行不能卡死,隨時要能中斷。
自動化最怕失控。如果用 for step in steps 的阻塞迴圈,等圖片時就沒辦法即時回應 ESC 或暫停。
挑戰 C:同一個圖示出現在多種情境,只比對圖片會點錯。
例如多個關卡的按鈕外觀完全一樣,只有旁邊的文字不同。單靠影像比對無法分辨。
挑戰 D:畫面有多種可能狀態。
彈窗、隨機事件、成功或失敗畫面,下一步要看「哪一張圖先出現」,不能寫死順序。
A:拆行程加 socket。
UI 只負責把 {folder, command} 以 JSON 送到 5200。如果連線被拒(Core 沒開),就用 ShellExecuteW(..., "runas", ...) 以管理員身份拉起 Core 後重送一次。
B:callback 串接,不用阻塞迴圈。
每個步驟完成後呼叫 on_done(backup_plan),由 check(index, backup_plan) 決定下一步的索引。失敗策略只是改下一步的索引:退回上一步重試是 index -= 2,略過是 index += 1。中斷靠 threading.Event(ESC 終止、空白鍵暫停、TAB 跳下一步),所有等待都用 NEXT_EVENT.wait(timeout) 取代 sleep,因此能被即時喚醒。這也是 README 說的「沒有停不下來的迴圈」的實作基礎。
失敗策略用步驟尾綴宣告:
尾綴 意義 逾時
(無) 找不到就暫停,等人處理 15 秒
? 找不到就略過 1 秒
↑ 找不到就退回上一步重試 0.4 秒
C:先定位,再用 OCR 驗證。
evolve2@II 這類寫法會先找出所有符合的圖片位置,再對每個位置截圖做 OCR,文字符合的才是點擊目標。這些 OCR 在平行執行緒中進行,並且共用一個 thread_event,任何一個匹配成功就通知其他執行緒停止。另外 skip#2 可以指定第幾個,找到多個相同圖片時不用靠 OCR 也能選位置。多個相近的候選框則用 NMS 去除重疊。
D:多圖同時偵測。
圖A|圖B 會同時開多個執行緒各找一張,先找到的點擊,並以 thread_event 通知其他執行緒停止。適合「成功或失敗畫面二選一」「有彈窗就關」這類分支情境。