用python来自动玩类似跳一跳的小游戏

最近春节,qq上出了一个叫穿越福城的小游戏。游戏的玩法类似挑一挑,也是通过一个个木桩。只不过把跳的过程变成了搭梯子。按的时间越长,梯子越长。梯子过长或者过短小企鹅都会掉下去,游戏失败。我的目的是用python来实现自动玩游戏。(主要原因是我手残。。没办法,只好另辟蹊径,技术开挂)。在刚开始构思的时候,我其实是觉得挺简单的一个小脚本就能搞定。但是在实际编码和测试的过程中,我越发觉得想要完成一个简陋版本,勉强能用的版本非常容易。但是想要做到稳定性好,准确率高实在是不容易。下面我就把我这两天的编码和完善过程记录下来。

先说说我的总体思路。通过adb的截图功能获得截图,然后根据获得的截图计算出应该按压多少毫秒,再通过adb shell input swipe来按压指定毫秒数。循环往复,理论上可以一直刷到无限分。

这里面的难点显然是在第二步,即怎样根据截图计算毫秒数呢?

那我们首先要思考毫秒数和什么变量有关,再从图片中提取或者计算出变量即可。梯子是按得时间越长就越长,所以可以认为按得时间t应该和木桩之间的距离成线性关系。那我们怎样从图片上计算起始木桩和目标木桩之间的距离呢?第一想法肯定是在图片中找到起始点x0,y0,再找到目的点x1,y1.计算这两个点的欧氏距离。但是玩这个游戏会发现,如果木桩之间的距离很长,游戏中会拉高视角。所以要想获得木桩之间的实际距离,不能光考虑像素之间的距离,还要考虑视角高度。视角越高,一个像素点代表的实际距离就越长。所以综上,时间和两个因素有关,一是像素距离,而是视角高度。

第一个因素像素距离,想要获取这个参数的关键在于怎样确定起点和终点。一个图片在计算机中就是一个矩阵,在矩阵中怎样找到起点和终点?这就需要明确起点和终点的特征。根据特征找到满足特征的像素,进而就可以找到起点和终点。从截图可以发现,起点的明显特征就是深色的小企鹅,在明艳的背景中,只有小企鹅是深色的。所以找图片中rgb均小于50的像素点,就可以定位小企鹅所在的位置。终点就更好确定了,每个木桩的中心都有一块红色菱形。这些红色菱形的rgb都是一样的。找这个rgb值就可以找到这些菱形,那么怎么知道哪个菱形是目标点呢?观察可知,在小企鹅上方的,且满足红色菱形的是目标点。找到了起点和终点,我们就可以算出来dis(distance)

第二个因素是视角高度。这个就比较抽象了,改用什么表示呢?视角高度不好直接计算,但是有办法体现出来。视角高度越高,相同面积的东西所占的像素数量就越少,也就是近大远小。而观察游戏可知,每个木桩上的红色菱形的面积是一定的。所以我们可以用目标点红色菱形的像素数(size)来表示视角高度。像素数越多,视角高度越低;像素数越少,视角高度越高。

现在找到了计算dis和size的方法,那么按压时间t怎么计算呢?首先设置一个参数a,用于调整系数。

t = a*dis/sqrt(size)

dis越大,显然按压时间应该越长。size越大,说明视角越低,显然按压时间应该越短。那么为什么size要开一个平方根呢?这是因为dis是一次的长度,而size是二次的面积。所以要开一个平方根,保证量纲一致。a由实验测得。经过实验我发现a=30左右的时候,程序运行良好,虽然做不到每次都非常精准,但是大部分时候都是可以通过的。

到这里为止,我的小程序已经基本可以大部分时候100+了。运气比较好的时候我还拿到了273分。但是在一次次测试中也暴露出了很多问题。接下来开始我的调试之路。

1、广告干扰

观察上图,本来我的起始点是根据颜色判断的。结果广告中也出现了相同的色彩,从颜色来确定起始点的路子走不通了,怎么办?那只好找其他特征。什么特征呢?那就是

1、企鹅是实心的

2、企鹅是近似圆形的

我之前都是用PIL的,现在不根据颜色了,就需要用更加高级和复杂的python-opencv了。先二值化,只保留深色部分,然后用findContours找边缘,然后筛选出满足条件的contour即可。这样一来找对起点的准确率就极高啦。

第二个问题:准确率不高。显然我建立的模型和游戏的内部逻辑还是有一定的差距。

怎么解决?从数学上来说,就是要确定一个二元函数time=f(dis,size).为了找到这个函数到底是啥,我首先得采集足够多的样本点。

采集了300个样本点后,绘制出dis-size函数,发现如下图所示

这说明和我原先想的不一样,这不是一个连续函数,而是一个离散的函数。(dis,size)一共只有十六中组合。

既然这样就好办了。先kmeans聚类,划分成16类,找到每一类的dis,size,time,作为table记录到程序中。每次获得一个dis和size,查找table,找到最先进的dis和size所对应的time,然后用adb按相应的time即可。

经过这么已改进,准确率极高。几乎每一次都是三分。当然其中的time参数由于是取得平均数,和真正的准确值还有一定的差距,在偶尔不是三分的情况下还要对time进行改进。

经过这些改进这个程序可以说已经基本可以跑了。我写了两个版本的代码,一个是aaa.py,这个是使用t=dis/sqrt(size)方法的;另一个是bbb.py,这个是使用table版本的。table版本的正确率更加高。

代码放在github上:

即使经过了改进,还是有一些问题,不过出现的次数很少

1、这个小企鹅有时候会跳起来转个圈,截图如果截取的是小企鹅挑起来的图会造成误判断

2、有时候游戏中的一些背景建筑,尤其是塔之类的,会把小企鹅挡住一小块,导致findContours函数无法将小企鹅识别为一个整体。

猜你喜欢

转载自www.cnblogs.com/digdig/p/10343968.html