Skip to content
Andrew's Playground
Go back

用 Python 打造手遊自動化 Bot(上篇)— 從零到 MVP

前陣子連假無聊下載了款 Roguelike 的卡牌手遊來玩,玩了幾天後發現這樣不行耗費太多時間了,突然靈機一動現在 AI 這麼方便搞不好可以弄個自動化刷關的程式,這樣就可以解放我的雙手了。

這個系列預計會有三篇,上篇講從零開始到能跑的 MVP,中篇深入 Unity 注入與卡牌策略,下篇聊重構、監控和一個月的回顧。


🎮 動機與目標

這款遊戲叫 Card Guardians,是一款 Roguelike 卡牌手遊。

遊戲機制很簡單:每次進入關卡的卡牌都相同,透過遊玩時打怪、選牌、升級的變化來豐富遊戲,一路推進到 Boss。完成一輪關卡後升級裝備就會比上一次更強一點,透過不斷地刷關來慢慢地變強。但問題是,要刷金幣、升級裝備需要大量的時間,而且這是一個無止境的循環,刷久了實在是有點悶:

進關 → 戰鬥 → 領獎 → 再進關

每一輪大概要花 20-30 分鐘,一天如果想刷個幾場,兩三個小時就去了。身為工程師,這種事情當然不能忍。

目標很明確:寫一個 Bot,讓它自動完成整個刷關循環,我只要偶爾看一下有沒有出問題就好。

有了想法後馬上跟 Claude 討論,初步規劃是透過 iPhone Mirroring 把手機畫面鏡像到 Mac 上,直接截圖投影的畫面下來,丟給 Python 程式做畫面判斷,決定要執行的卡牌動作後,透過 PyAutoGUI 直接控制滑鼠來取代手指的觸控,達到模擬玩遊戲的效果。

🛠️ 技術選型

跟 Claude 討論完後,最終選定的技術組合是:

為什麼不用 VLM / OCR?

一開始也想過要不要用 Ollama 跑個本地模型來辨識遊戲畫面,但想了想這遊戲的 UI 是固定的 — 按鈕永遠長那樣、畫面切換有固定的特徵元素。對於這種固定 UI 的場景,Template Matching 就是最簡單、最可靠的方案。

而且這也是最快可以實驗的方式,不需串 API、不需要調參數,截一張模板圖片就能用。先用最簡單的方案解決問題,後續如果要增強再慢慢增加功能,不要過度設計。


🧠 核心架構:用「狀態」的思維來辨識畫面

整個 Bot 的核心邏輯可以用一句話概括:截圖 → 辨識當前畫面 → 執行對應動作 → 重複。

遊戲的每個畫面就是一個狀態,而 Bot 要做的就是辨識出當前狀態,然後執行對應的動作讓遊戲推進到下一個狀態。

狀態定義

首先定義一個 GameScreen enum,列出所有可能的遊戲畫面。

畫面特徵(Screen Signature)

每個畫面都有獨特的視覺特徵。例如主選單有特定的按鈕、戰鬥畫面有血條和卡牌區域。我為每個畫面定義了一組「特徵模板」,藉此來辨識畫面。

主迴圈

Bot 的主迴圈就是不斷重複三個步驟:

while True:
    1. screenshot = capture()           # 截圖
    2. screen = detect(screenshot)      # 用所有 signature 比對,找出當前畫面
    3. decide_action(screen)            # 根據畫面執行對應動作
    sleep(interval)

detect() 會把截圖跟每個 ScreenSignature 的模板一一比對,用 OpenCV 的 matchTemplate() 計算相似度,超過閾值就算匹配。所有 required 模板都匹配的那個 signature,就是當前畫面。

decide_action() 則是一個大的分派函式 — 如果在主選單就點進關卡、如果在戰鬥就打牌、如果在獎勵畫面就領取並繼續。把複雜的遊戲流程拆成一個個獨立的狀態處理,每個狀態只需要專注自己的邏輯就好。


🤖 Vibe Coding

從開起這個念頭後,到完成一個初步的原型,總共花了一天多的時間,現在有 AI 可以輔助,真的可以在極短的時間內做出一個原型來測試,基本上只要動一張嘴就可以了,花比較多時間的反而是在確認截圖與確認點擊的位置上,畢竟遊戲的玩法還是自己比較清楚,有些東西還是得人工確認,但也不排除是我口袋的深度限制了 AI 的能力 XD

Template Matching 引擎

最初的引擎很陽春但有效:

  1. 截圖:用 screencapture 指令抓取遊戲視窗
  2. 載入模板:事先截好的各種 UI 元素小圖(按鈕、圖示、文字等)
  3. 比對:用 cv2.matchTemplate() 在截圖中搜尋模板
  4. 判斷:匹配度超過閾值(通常 0.8-0.9)就算找到了
  5. 執行:用 PyAutoGUI 點擊匹配位置的座標

引擎跑起來後,接下來要面對的是模板本身的品質問題。

模板裁切的眉角

模板的裁切也是要一點經驗的:

最好的做法是只裁切目標元素本身,留一點點邊距但不要包含會變動的背景。這需要一些經驗和反覆測試。


🖥️ 執行環境的演進:iPhone Mirroring → PlayCover

最初方案:iPhone Mirroring

一開始的方案很直觀 — 用 macOS 的 iPhone Mirroring 功能把手機畫面投射到 Mac 上,然後截圖這個鏡像視窗。聽起來合理,實際上跑起來也沒問題,但是當初想寫這個 bot 是為了解放我的雙手,但現在完成後我只能在一旁看我的電腦透過滑鼠在玩我的手機 ???

轉移:PlayCover

後來發現 PlayCover 這個模擬器,可以直接在 Mac 上執行 ipa 檔,花了點時間研究一下,順利的把遊戲從 iPhone 鏡像,轉移到直接在 Mac 上模擬,不過這樣做有個很大的問題,就是我之前截的圖都要重新再截過,因為兩者的解析度和渲染結果不同,之前截的模板全部不能用,要重新截取,而且座標系統也要再次確認過,我的半天就這樣又沒了🫠


📝 本篇小結

從一個「不想手動刷關」的念頭開始,兩天內就做出了一個能自動循環刷關的 MVP。回頭看這段過程,有幾個心得:

  1. 先求能動,再求完美 — Day 1 的 Bot 很粗糙,很多 hardcode,但它能跑。能跑才有東西可以迭代。
  2. 選最簡單夠用的技術方案 — Template Matching 不酷、不潮、不需要 GPU,但對固定 UI 的遊戲來說它就是最好的選擇。
  3. AI 輔助開發的威力 — 整個技術架構是跟 Claude 一起討論出來的,很多 OpenCV 的用法也是即時查問的。一個人摸索可能要花一週的事,有 AI 的輔助兩天就搞定了。

不過到這裡只是一個開始。MVP 能自動刷關了,但它其實很脆弱 — 碰到一個意外彈窗就會卡住、出牌策略就是亂打、偶爾還會辨識錯畫面做出離譜的操作,導致 Bot 卡死,甚至還誤觸遊戲內購的按鈕…

下一篇(中篇)會聊聊怎麼讓 Bot 變得更聰明也更實用:逆向工程 Unity 引擎來注入控制、建立完整的卡牌辨識系統、以及設計出牌策略。

💡 最後,如果你也有類似的需求,想要解放你的雙手,非常推薦去找 AI 聊聊看,就算沒有程式經驗也完全沒問題,把你的想法丟出來跟 AI 討論就對了,搞不好你也能做出屬於自己的自動化工具。如果有任何問題也歡迎私訊我 :)


Share this post on:

Next Post
Hello World - 為什麼開始寫部落格