最近被微信的一張圖片刷屏了政勃,只要一打開朋友圈,都能看到同樣一張圖兼砖。本以為又是吃雞的畫面奸远,一直沒去理會。直到偶然有一天刷頭條才知道讽挟,繼小程序之后懒叛,微信的小游戲又橫空出世了,不得不說耽梅,騰訊在這些方面做的還蠻有前瞻性的薛窥。
而所謂的微信跳一跳,就是微信小游戲平臺上線以來眼姐,最火爆的一款小游戲诅迷。我玩了一會佩番,發(fā)現(xiàn)這個游戲的邏輯其實(shí)挺簡單的,只需要控制按下去的時間罢杉,就能控制跳出去的距離答捕。控制時間這種事情對于人類是最不擅長的了屑那,何不交給計算機(jī)自己來做呢拱镐?廢話不多說,先來嘗試一下持际。
adb shell方式
通過嘗試沃琅,此種方法對于沒有root的普通手機(jī)也適用,那我們就先用這種方法來嘗試一下精確控制的快感蜘欲。
首先手機(jī)的usb調(diào)試模式必須得打開益眉,然后接入電腦,執(zhí)行以下命令:
adb shell
進(jìn)入命令終端之后姥份,我們就可以實(shí)現(xiàn)許多在linux層可以干的事了郭脂,當(dāng)然包括模擬觸摸事件。
如執(zhí)行以下命令澈歉,可實(shí)現(xiàn)在屏幕坐標(biāo)為(200,300)的點(diǎn)上實(shí)現(xiàn)500ms的觸摸事件展鸡。
input swipe 200 300 200 300 500
通過最后一個參數(shù),就可以實(shí)現(xiàn)對觸摸時間進(jìn)行精確的控制埃难,如果能夠找出時間與距離的對應(yīng)關(guān)系莹弊,那么這個游戲?qū)ξ覀儊碚f最難的地方就被破了,哈哈涡尘。
以下是我在小米mix2平臺實(shí)測出來的數(shù)據(jù):
時間t(ms) | 距離d(cm) | 距離d(pix) |
---|---|---|
100 | 0.4 | 63.52 |
200 | 0.8 | 127.04 |
300 | 1.2 | 190.56 |
400 | 1.8 | 285.84 |
500 | 2 | 317.6 |
600 | 2.6 | 412.88 |
700 | 3 | 476.4 |
800 | 3.4 | 539.92 |
900 | 4.1 | 651.08 |
以下是繪制出來的圖像:
如果圖像是這樣的話忍弛,那真的是太完美了,可以直接就用一條直線去代替了考抄,不用再麻煩地建立查找表细疚,接下來當(dāng)然就是解方程組的問題。
設(shè)直線為t=kd+b
川梅,選兩個靠譜的點(diǎn)(0.4,100),(4.1,900)
代入解得k=216.2,b=13.5
疯兼,所以時間的計算公式為:
t=216.2*d+13.5
好了,有了adb和這個公式之后挑势,再加一把尺子镇防,我們就能想玩多少分就玩多少分了啦鸣,當(dāng)然還得看你耐心如何潮饱。
腳本自動控制
經(jīng)歷過adb控制的話,相信你一定能夠體會到這個過程是多么的讓人煩躁诫给,為了裝一個b容易嗎我香拉。如果能夠有這種想法那就對了啦扬,枯燥的過程能用計算機(jī)解決的,絕對不應(yīng)該讓人親自去干凫碌。
那如果要讓手機(jī)自動運(yùn)行這套思想扑毡,有什么難點(diǎn)需要跨越呢?
其實(shí)對于自動處理來說盛险,最難地方的在于坐標(biāo)點(diǎn)的獲取瞄摊,也就是說,我們在用直尺測量的這個過程苦掘,要用程序來模擬换帜。那么問題來了,要獲取距離鹤啡,就需要得知兩點(diǎn)的具體坐標(biāo)惯驼,即起跳點(diǎn)和落地點(diǎn),這個坐標(biāo)該怎么來呢递瑰?
這時我聯(lián)想到曾今做過的飛思卡爾智能車比賽祟牲,當(dāng)時做的是攝像頭組,可以基于這些思想來搞一套簡單的圖像識別啊抖部,說干就干说贝。回到家我連一直在追的連續(xù)劇也沒看慎颗,一直干到深夜狂丝。
經(jīng)過了解,按鍵精靈這個平臺非常滿足我的需求哗总,他提供了許多api几颜,關(guān)鍵的api有以下幾個:
FindPic//查找圖片
Tap//點(diǎn)擊屏幕
Delay//延時
GetPixelColor//獲取指定坐標(biāo)的顏色
CmpColor//比較兩個顏色是否相同
Touch//觸摸屏幕一段時間
大概思路就是,通過FindPix這個接口讯屈,實(shí)現(xiàn)起跳點(diǎn)的定位蛋哭,這個很好實(shí)現(xiàn),因?yàn)槠鹛c(diǎn)的長相不會變涮母,逃不出這個接口的手掌心谆趾。
主要難點(diǎn)在于落地點(diǎn)的識別算法上面,我嘗試過很多方法叛本,最后覺得最有效的還是下圖這種識別方式:
A點(diǎn)是起跳點(diǎn)沪蓬,這個已知,通過這個點(diǎn)延伸一條虛線出去来候,現(xiàn)在我們設(shè)一動點(diǎn)P跷叉,從P0滑動到A,在滑動的過程中檢測P點(diǎn)當(dāng)前位置的像素,有沒有顏色跳變云挟,如果有的話那么此時P點(diǎn)的坐標(biāo)就是B2點(diǎn)的坐標(biāo)梆砸。
接著通過A點(diǎn)和B2點(diǎn)算出兩者間的距離,得出的距離再根據(jù)實(shí)際方塊大小稍微調(diào)小一點(diǎn)园欣,差不多就是AB線段的長度了帖世。
好了,方法說完了沸枯,想想其實(shí)蠻簡單的日矫,當(dāng)年飛思卡爾也是用這種low到不行的方法來獲取各種邊界,最終才勉強(qiáng)把賽道識別出來绑榴。
方法如上所說搬男,接著到了計算環(huán)節(jié),只有經(jīng)過精密的計算之后彭沼,才能變換為代碼自動運(yùn)行起來缔逛。
上圖是我的一個計算過程,偷個懶直接上原始圖姓惑,有點(diǎn)亂褐奴。
這里簡要說明一下:
- w,h
屏幕的橫向和縱向分辨率 - A(x,y)
起跳坐標(biāo),由FindPic得出 - P(x,y)
AP0線段上的動點(diǎn) - a
虛線與水平線的夾角于毙,tan(a)=0.58
這個很關(guān)鍵敦冬,知道了A點(diǎn)坐標(biāo),還需要知道這個夾角才能把虛線定下來唯沮,這個角通過測量加計算脖旱,算出來tan(a)=0.58 - B_dir
落地點(diǎn)位于屏幕中心的位置,-1代表左邊介蛉,1代表右邊
最終得出的結(jié)論有如下:
- P0坐標(biāo)
B_dir=-1:
P0_x=0
P0_y=A_y-A_x*tan(a)
B_dir=1:
P0_x=w
P0_y=A_y-(w-A_x)*tan(a)
- tan(a)
tan(a)=0.58
- P_y與P_x的關(guān)系
P_y=A_y-B_dir*tan(a)(P_x-A_x)
代碼
有了以上結(jié)論萌庆,寫程序就順利成章了。按鍵精靈采用MQ語言币旧,大概看了下践险,和老古董VB長得好像,古董歸古董吹菱,能實(shí)現(xiàn)功能就好巍虫,以下是代碼,各位看官慢慢品味吧鳍刷,順便幫忙找找bug占遥。
Dim w=GetScreenX(),h=GetScreenY()
TracePrint "w,h:", w, h
Dim A_x,A_y,B_x,B_y,B_dir,B2_x,B2_y
Rem retry
TracePrint "begin"
//判斷是否已經(jīng)失敗
Dim retryButton_x,retryButton_y
FindPic 0, (h-h/8), w-1, (h-h/8*2), "Attachment:retryButton.png", "000000", 1, 0.9, retryButton_x, retryButton_y
If retryButton_x > 0 And retryButton_y > 0 Then
Tap retryButton_x, retryButton_y
TracePrint "retry"
Delay(3000)
End If
//獲取A點(diǎn)坐標(biāo)
FindPic 0, h/2-100, w, h/4*3, "Attachment:chess.png", "000000", 1, 0.9, A_x, A_y
A_x = A_x + 22
A_y = A_y + 97
TracePrint "A:", A_x, A_y
//判斷目標(biāo)方向
If A_x >= w / 2 Then
B_dir = -1//B在左
Else
B_dir = 1//B在右
End If
//遍歷路徑獲取B/B2點(diǎn)坐標(biāo)
Dim P0_x
Dim P_x,P_y,delta_x
Dim P_x_pre,P_y_pre
If B_dir = -1 Then
P0_x = 0 + 100
delta_x = 2
Else
P0_x = w - 1 -100
delta_x = -2
End If
Dim tan_a = 0.58
P_x_pre = P0_x
P_y_pre = A_y - B_dir * tan_a * (P0_x - A_x)
For P_x = P0_x To A_x Step delta_x
P_y = A_y - B_dir * tan_a * (P_x - A_x)
//對比顏色
Dim color_pre = GetPixelColor(P_x_pre, P_y_pre)
Dim ret=CmpColor(P_x, P_y, color_pre, 0.99)
//TracePrint "P:", P_x, P_y, "ret:", ret
If ret = -1 Then
B2_x = P_x
B2_y = P_y
Exit For
End If
P_x_pre = P_x
P_y_pre = P_y
Next
TracePrint "B:", B_x, B_y
TracePrint "B2:", B2_x, B2_y
//計算距離
Dim dis_pix,dis_cm
dis_pix = Sqr((A_x - B2_x) ^ 2 + (A_y - B2_y) ^ 2) - 90
dis_cm = dis_pix / 158.8
TracePrint "dis_pix:", dis_pix
TracePrint "dis_cm:", dis_cm
//計算按鍵時間
Dim t
t = dis_cm * 216.2 + 13.5
t = CInt(t)
If t < 100 Then
t = 100
End If
TracePrint "t:", t
//發(fā)送事件
Touch w - 100, (h / 4 * 3), t
TracePrint "end"
Delay 1600
Goto retry
屏幕坐標(biāo)獲取技巧
找到設(shè)置,打開指針位置的選項(xiàng)输瓜,可以很方便的獲取任意位置得坐標(biāo)瓦胎。好了芬萍,以上便是此次玩跳一跳所用的全部姿勢,現(xiàn)在感覺好累凛捏,讓我的手機(jī)自動跳吧,我休息去了~~~