Python | OpenCV 專案:天堂私服遊戲輔助(四)目標優先序選擇
📑 目錄
⚠️ 免責聲明
本文章內容僅供學術研究與電腦視覺技術學習之用途,所有程式碼與技術說明均以教育目的為出發點。
- 本文作者不提供任何形式的輔助程式販售、散佈或商業服務。
- 本文所有範例程式僅限在自行架設的私有伺服器環境中測試,不得用於任何正式營運的線上遊戲伺服器。
- 使用遊戲輔助程式可能違反個別遊戲的使用者條款,並導致帳號封鎖、法律責任等後果,讀者須自行承擔一切相關風險與責任。
- 本文技術內容若被用於任何違法或損害他人利益之行為,作者概不負責。
- 私有伺服器的架設與使用涉及遊戲著作權相關法律問題,讀者應自行評估所在地區的法規,並確認於合法範圍內使用。
📚 前言
在上一篇 (三)YOLOv8 怪物偵測整合 中,我們完成了雙執行緒偵測架構,並做出 live(bbox)/ grid(扁平菱形小地圖) 兩種預覽模式,也支援執行中熱換模型。
本篇加入 目標優先序選擇:當畫面同時出現多隻怪物時,依使用者設定的優先類別順序與距離畫面中心的遠近,選出最值得攻擊的目標,並在 live 與 grid 兩種預覽中都以紅色特別標記。
系列總覽:
| 篇次 | 主題 |
|---|---|
| 一 | 主程式 GUI 框架與 HP/MP 血量監控 |
| 二 | 自動補藥 |
| 三 | YOLOv8 怪物偵測整合 |
| 本篇(四/最終篇) | 目標優先序選擇 |
🎯 本篇目標
- 建立
target_selector.py:依「類別優先清單 + 距離畫面中心」排序,從偵測結果挑出最優先目標 - 微調
detector.py:render()/render_grid()接收target,讓 live 模式在鎖定目標框上畫紅色、grid 模式把鎖定格塗紅 main.py更新:SharedState新增target欄位;detection_loop呼叫TargetSelector.select()後把結果餵進render()- UI 新增「優先類別」輸入欄(逗號分隔),預覽區底部顯示當前鎖定目標;優先清單可執行中熱切換
🗂️ 本篇新增/更新檔案
1 | lineage_assistant/ |
💻 目標優先序模組:target_selector.py
排序規則(由高到低):
- 類別在優先清單中的位置越靠前,優先度越高
- 未列入清單的類別排最後
- 同優先度時,距離畫面中心越近越優先(減少滑鼠移動距離)
Thread 2 每秒會跑幾次
select(),若目標每幀都寫 log 會洗版,所以這裡用_last_key只在「目標實際切換」時才寫一筆。
1 | # target_selector.py |
🔧 detector.py
Part 3 的 annotate() 本來就能接 target(鎖定的框畫紅色),只是 render() 派發器沒把它傳下去、render_grid() 也還沒用到。本篇補兩件事:
render()加上target參數並派發下去render_grid()新增target參數,命中鎖定目標的那一格填紅色(其他怪物仍是黃色)
以下是完整的更新後 detector.py(imports 與模組常數 VIEW_EW / VIEW_NS / GRID_HALF / CANVAS_W / CANVAS_H / get_game_roi / get_tile_px 沿用 Part 3,改動處用 # ← 本篇新增 標註):
1 | # detector.py |
💻 執行緒架構(本篇)
相較 Part 3,差異只在 Thread 2 多繞一趟 TargetSelector.select();Thread 1 與 Main 完全不變。
1 | Worker Thread 1 (monitor_loop) ← 不變 |
💻 主程式:main.py(最終篇版本)

圖:整合目標優先序選擇的主程式,Thread 2 呼叫 TargetSelector 選出目標後以紅框標記,UI 顯示當前鎖定目標的名稱與信心度
⚠️ 注意事項
🎯 優先序與類別名稱
- 類別名稱要與訓練時完全一致:大小寫、底線要跟
data.yaml或classes.txt對得上,拼錯只會變「未列出」落到最後。 - 未列入優先清單的類別仍會被偵測,只是排序時放最後;全部都沒列也 OK,這時會退化成「距離畫面中心近者優先」。
- 距離基準是畫面中心:若要改用角色實際位置(ROI 中心),把
selector.select()的frame_center換成get_game_roi算出的中心即可。
🧵 與 Part 3 的熱切換共存
- 優先清單即時生效:
_poll每 200ms 從「優先類別」Entry 把字串解析成 list 寫回selector.priority,執行中隨便改都下一幀生效,不用停啟。 min_conf預設 0:detector.conf已經先濾一次,這裡再濾一次會讓 UI 滑桿失去意義、目標也可能忽有忽無。想只鎖定很高信心的目標時才手動拉高。- 熱換模型時 target 不會殘留:Thread 2 每輪都重算 target;
detector.enabled=False或模型未載入時會直接state.update(target=None),預覽的目標 label 會立刻回到「—」。
❓️ 新手常踩的雷
selector.priority = new_list是整包換:字串解析的結果一次 assign,CPython 下是原子操作;不要用.append()累加,否則熱切換時會越加越長。d is target用 identity 判相等:annotate與render_grid都用d is target判斷是否為鎖定目標,所以不能 deep-copydetections,否則紅框永遠畫不出來。- Entry 內容留空:
_parse_priority會回傳空 list,此時TargetSelector退化成純距離排序,不會崩潰。
🎯 結語
本篇也是整個天堂私服遊戲輔助系列的最終篇。 從 Part 1 的 tkinter GUI 與 HP/MP 血量偵測、Part 2 的 PostMessage 自動補藥、Part 3 的雙執行緒 YOLOv8 偵測整合,到本篇的目標優先序選擇,整套輔助程式的視覺辨識 → 狀態判讀 → 目標決策核心流程到這裡已經完整。
至於更進一步的 自動攻擊怪物 與 自動撿取道具,因為涉及主動向遊戲下指令(攻擊熱鍵、滑鼠點擊),在法律與遊戲條款上相對敏感,本系列就不再實作。對有興趣延伸的讀者而言,前四篇打下的基礎已涵蓋核心技術 —— 鎖定後怎麼按下攻擊鍵、偵測到 item 類別後怎麼點擊,本質上都是把 SharedState.target / SharedState.detections 接到既有的 PostMessage 或滑鼠 API 上 —— 技術上不困難,是否實作與如何使用,請自行評估所在地區的法律與風險。
📖 如在學習過程中遇到疑問,或是想了解更多相關主題,建議回顧一下 Python | OpenCV 系列導讀,掌握完整的章節目錄,方便快速找到你需要的內容。
註:以上參考了
Ultralytics YOLOv8 官方文件
Python math.hypot 文件
Python queue.Queue 文件
tkinter ttk.Combobox 文件