手游自动挂机脚本开发历程
事件起因
國慶節期間,因為工作相對閑暇,自己鬼使神差地下載了一個夢幻西游手游玩了幾天,結果一周就這么過去了,一玩起游戲來,那就是白駒過隙啊。節日過后,游戲自然是沒時間再玩了,畢竟有一大堆開發任務正一個個排著隊等著去搞。時間一晃就到了兩周前,大概是11月底的時候,一個朋友跟我說他玩碧藍航線,每個月都要花20多塊錢買腳本。當時聽到腳本居然還要花錢去買時,作為一個程序員,不知道哪里來的正義感,決定自己給他寫個免費的腳本,能讓朋友省去一個月20塊的腳本錢去叫外賣也算是用腳本掙錢了。當然如果能有別人也來用自己寫的腳本,那當然更好,能幫到更多的人,由此小弟便踏上了一條游戲腳本不歸路。。。
初識按鍵精靈
初次寫腳本,小弟我也是一臉懵逼,以前完全沒寫過游戲腳本,當時牛皮吹的爽,現在不知咋搞心理有點慌。無奈只能調研下現在市面上寫腳本的工具了,當時了解按鍵精靈,觸動精靈等現在用得比較廣泛的腳本工具。按鍵精靈應該是用的最多了,所以小弟就選擇了按鍵精靈來寫腳本。按鍵精靈分為PC版和手機版,小弟寫的手游掛機腳本,當然是選擇手機版了,然后按照教程,在android模擬器上安裝了按鍵精靈APP并且在PC上安裝了按鍵精靈手機助手,腳本編寫之路,就這么正式開始了,加油!!
按鍵精靈學習
初次上手按鍵精靈,還是有點蒙圈。不得不說,按鍵精靈是寫程序小白們使用的,所以函數的使用都封裝得很簡單,而且變量可以定義中文,較復雜的代碼可以自動生成,所以小弟我花了一天的時間基本上就把按鍵精靈的各個部分都熟悉了(這里沒有給按鍵精靈打廣告的意思,大家不要誤會。。。)按鍵精靈雖然說是腳本編寫,但是用的最多就恐怕就是用來寫游戲腳本了吧。雖然按鍵精靈確實寫腳本比較方便,但是還是有一些不足之處的。讓小弟最想吐槽的就是按鍵精靈的OCR功能,簡直是形同虛設,根本不能用,文字識別總是失敗(大概率失敗,一旦失敗,就又得重新找點,重新讓這個精靈識別,然后又是大概率失敗,過程之痛苦,我覺得程序員不應該忍受這種痛苦),即使識別成功了,實際用的時候也不一定能識別出來,令人不得不吐槽一下。所以下面小弟我就稍微總結一下按鍵精靈讓我感受到的優勢和缺點吧。
按鍵精靈的優缺點
| 語法簡單 并且配有代碼示例 | 部分顏色函數使用效果不好 |
| 配有實時抓取手機屏幕工具 方便邏輯編寫 | OCR模塊效果很差 使用麻煩 |
| 調試方便 有基本的調試工具 |
上面說到的OCR模塊效果很差,可以說是一個比較重要的問題,因為在游戲腳本編寫中,經常需要用到文字識別,只有識別到文字了,才能據此進行下面的操作。比如在《夢幻西游》手游中,找到了”師門任務“四個字,才能決定是否要開始師門任務,或者是返回任務已經被完成。個人認為,一個好用的OCR,才是游戲腳本的靈魂所在,其他的邏輯只是輔助而已。當然,我們還可以退而求其次,用判斷像素點顏色的方法來判斷是否有任務存在,小弟我在按鍵精靈OCR嘗試未果的情況下就是用了這種方式,對于PC版的掛機腳本,可以使用”大漠插件“來作文字識別,就小弟了解,這個插件效果還是不錯的,解決了文字識別的問題,讓很多PC上的掛機腳本穩定了很多。但是安卓系統下無法使用,所以這跟小弟無關,也就沒深入了解。另外順便再提一句,現在都9102年了,github上開源的中文OCR引擎咱整一個不香嗎,話題扯偏了,小弟我目前也沒用到AI的程度,后面會加入進來。。。
上面的截圖是按鍵精靈版的師門任務部分截圖,從圖中可以看出,按鍵精靈支持變量中文,并且沒有復雜語法,上手很容易,歷經了兩天的開發,小弟最終把師門掛機腳本,主線任務掛機腳本,抓鬼腳本寫完了,師門腳本和抓鬼腳本穩定都還可以,除了按鍵精靈運行一段時間自動崩潰以外,這個問題讓小弟束手無策,難道要再寫一個腳本在腳本崩潰以后再把腳本啟動起來?
和按鍵精靈分手
本來小弟滿懷期待地打算把寫好的腳本打包發送給同學,讓他試試,但是一道晴天霹靂讓小弟我幾近崩潰,打包居然要收費!!!,就19年下半年剛開始收費的,按月收費,最低30元(好像是),最高一百多。繳費越高,寫的腳本就能給越多的人使用,最低的30元腳本,只能給幾十個人使用。可是小弟我就自己用啊喂,我又不拿去賣錢,這也要收費。關于收費,小弟這里就不提了,畢竟這是人家自己的東西,咱也不好多說什么,沒辦法,只能和按鍵精靈說拜拜了,不是因為這區區30塊錢,而是小弟覺得這里不應該花這個錢,一來自己是程序員,本來就應該以更”程序員“的方式做這件事,二來是小弟是給別人無償幫忙寫腳本,這個錢不應該掏。
另一條路
放棄了按鍵精靈,就意味著放棄了那一套方便快捷的工具,放棄那兩天幸苦產出的代碼。小弟沒辦法,所有東西都要自己想辦法來解決了,通過使用按鍵精靈,小弟我發現,寫游戲腳本最重要的是解決兩個問題:
只要解決了上面這兩個問題,做一個基本的手游掛機腳本就足夠了,所以小弟我針對這兩個問題,開始網上新一輪的調研,在此期間也走過一些彎路,但是功夫不負有心人,最終還是摸索出了一條可行的路,下面就講述下小弟我的學習路程。
艱難的摸索
因為是手游腳本,游戲本身是運行在安卓模擬器上的,那么掛機腳本在小弟認為可以分為兩種,一種是直接運行在android模擬器下的,另一種是運行在PC上,通過發送遠程命令操作模擬器。小弟當時調研時理解還不夠深,所以選擇了第二種方式,通過adb(android debug bridge)將PC與模擬器連接起來的方式操作模擬器。實際上用第二種方式,將腳本打包在模擬器環境下直接運行效果才是最好的,當然,難度也會大不少。
Appium的學習
為了模擬用戶操作android,也就是解決第二個問題,小弟我首先了解到的是使用Appium,Appium是一個用于android系統的自動化測試工具,里面提供了很多模擬用戶操作的功能,包括點擊,滑動,截屏等等。當然他最強的之處并不在此,Appium能夠解析出當前App的前端控件,相比起之前按鍵精靈的點擊某個坐標的模擬操作方式,Appium能夠根據控件的id等屬性定位到某個具體的控件,定位之后做后續操作。這種方式的好處就在于,通過控件屬性定位坐標,跟屏幕分辨率無關。如果單單寫死一個坐標位置去點擊,手機換個分辨率就失效了,也是為什么手游腳本都固定一個分辨率的原因所在。
上圖是Appium連接成功后的配置截圖,其實核心參數就是deviceName,指定本地的模擬器地址就可以。在搭建Appium環境時,小弟我也是花了兩天的時間到處查閱資料和學習相關的用法,一開始使用的雷電模擬器,但是始終連接不上,最后換了個模擬器,用夜神模擬器后就成功了,所以如果連接不上模擬器,不妨換個模擬器試試,當然首先還是看看日志,有沒有打印什么錯誤。
初代腳本形成
小弟我使用python編寫此腳本,核心流程如下:
腳本啟動 -> 啟動Appium -> 調用Appium截屏 -> 判斷當前頁面狀態 -> 調用Appium模擬操作 -> 任務結束 退出腳本
連接的代碼如下:
突然醒悟 二代腳本形成
Appium上面也說過了,能解析頁面,類似于解析html的BeautifulSoup 一樣,但是游戲頁面哪有”前端“這種說法呢,哪有樹狀的控件能讓我解析呢,我用Appium捕獲到的頁面永遠都是一個大的Frame,然后里面什么也沒有,更別提解析了。。。
但是Appium底層也是調用的adb,那為何我不直接使用adb來完成所有這一切操作呢,既然Appium的優勢不復存在,使用他反而成為了累贅。所以小弟我把Appium去掉,重新更新了一版腳本,用python調用adb命令完成截圖,模擬操作等命令
腳本核心思路如下:
腳本啟動 -> 截圖到本地 -> 比對坐標點顏色 -> 判斷出于什么頁面 -> 執行具體操作 -> 刪除本地圖片 -> 重新截圖新一輪判斷
下面把核心代碼貼出來,完整代碼小弟我在文章后面會給出git倉庫地址,感興趣的同學可以clone一下看看
首先是用到的adb基本命令如下:
SCREENSHOT = "adb exec-out screencap -p > " # 末尾需加上截屏地址 TAP = "adb shell input tap " # 點擊屏幕 x y SWIPE = "adb shell input swipe " # 滑動屏幕以上分別是截屏保存到PC本地,點擊模擬器坐標x y 以及滑動模擬器屏幕,當然后面還有一些參數,參數根據需要加在命令后就行了,這里就省略掉參數吧
PC命令行中執行 adb 截屏命令
def get_screen_shot(self, path):cmd = Constants.SCREENSHOT + pathos.popen(cmd)核心函數 圖片像素顏色采集和比對
# 對比圖片像素顏色值def comparePixelColor(self, srcImg, color, position, simThreshold):# 計算歐式空間距離# 首先獲取 x 和 y 坐標的顏色值targetColor = self.getPixelColor(srcImg, position)# 再分別獲取 R G B 值red = targetColor[0]green = targetColor[1]blue = targetColor[2]diff_red = red - color[0]diff_green = green - color[1]diff_blue = blue - color[2]similarity = (1 - math.sqrt(diff_red*diff_red + diff_blue*diff_blue + diff_green*diff_green) / math.sqrt(255*255 + 255*255 + 255*255))if similarity > simThreshold:return Trueelse:return False# 獲取圖片坐標點顏色值def getPixelColor(self, srcImg, positon):srcImg = srcImg.convert('RGBA')str_strlist = srcImg.load()RGBA = str_strlist[positon[0], positon[1]]return RGBA以上兩個函數分別是獲取圖片中某個坐標點的顏色以及比對圖片中某個坐標點顏色的函數,對于比對顏色函數,計算歐式空間距離,然后按照比例算出相似度,在腳本中,小弟認為相似度大于 0.9以上才認為是相似的
還有一些就是邏輯部分的代碼了,這部分代碼并非核心代碼,小弟這里就不貼出來了,有興趣的同學可以github上看
一段路程的結束 若有所思
至此,游戲掛機腳本就到一段落了,游戲腳本小弟自己使用沒有什么問題,但是離給別人使用還有很長一段距離,主要是adb截屏到本地耗時實在是太久了,截屏一次2s,這個是硬傷。
如果要優化這個問題,就必須讓腳本執行在android系統中,通過讀取android系統下的設備文件實時獲取屏幕數據(需要root),我想這也是為什么按鍵精靈能做到顏色比對如此之快的原因,因為前面也提到了,按鍵精靈手機版由兩個部分組成,一個是”按鍵精靈手機助手“,這是安裝在PC上的;另一個是”按鍵精靈手機版“,這是安裝在手機上的APP
在調試開始前,按鍵精靈會要求兩者連接。我想,按鍵精靈是在PC上完成腳本的編寫(手機助手編寫腳本),然后連通手機上的APP,把寫好的腳本傳到APP中去運行,由于是運行在手機測,和我的腳本就不同,它可以直接讀取設備文件。這也解釋了為什么按鍵精靈要root權限,因為沒有root權限就無法讀取文件獲取屏幕像素信息。另外,按鍵精靈的”抓抓“里有一個截屏功能,如下圖:
通過這個按鈕的截屏時間也差不多2s左右,我想按鍵精靈這個2s應該跟我上面的使用adb傳文件到本地耗時2s原理是一樣的,因為都是從模擬器上截圖到本地,應該都是走的adb,所以都是2s耗時
接下來的優化
上文提到了最好的方式是讀取設備文件獲取屏幕像素信息,而非截圖,我自然是打算把優化方向放在腳本的執行環境上了,接下來可能會改用java編寫,讓腳本運行在android系統下,關于讀取android屏幕數據(FrameBuffer),這里有一篇寫得比較好的文章大家可以學習一下,牽涉到android底層代碼,讀取FrameBuffer獲取屏幕數據,路雖難,但只要肯琢磨,一定能理解
以上就是兩周以來對腳本的研究近況,因為筆者水平有限,文中難免有表述不準確的地方,還請大家指出,共同學習進步~
項目github地址:https://github.com/dz-ssk/GameScript
總結
以上是生活随笔為你收集整理的手游自动挂机脚本开发历程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《大数据之路:阿里巴巴大数据实践》-第1
- 下一篇: android 自定义地图标注,Andr