微信跳一跳小程序原理比较简单,抛开声音要素,跳的距离与拇指按压时间成正比例,假设每次跳动距离都等于拇指按压时间*常数系数,这个游戏就变成了根据跳动距离求解按压时间,于是乎我在PC端用安卓模拟器和C#实现了一个跳一跳辅助程序
需求分析
思路
- 在模拟器确定起点和终点的位置坐标,勾股定理算出两点距离
- 一个可以实时调节大小的系数,乘以距离算出鼠标按压时间
- 根据算出的按压时间模拟鼠标按压动作
可行性
针对上述1:如果想实现完全自动跳跃,肯定要用到图像匹配,从跳一跳界面来看,起点旗子的图形是固定的紫色象棋,想确定位置比较容易
终点的图形是新落的方块,这个方块素材目前看来官方会不断更新,如果想通过维护一个图形素材库,用来匹配终点的话非常麻烦。那么通过分解图像算出来呢?新落下的方块总是出现在界面左上或右上方,可以先取界面角落的像素点确定背景色(因为背景色会变化,需要每次起跳前确认),然后从界面左上至右下遍历像素点,比较与背景色的色差,先出现色差的区域既是新落下方块的坐标区域,这样可以吗?很难实现,首先方块颜色不是单色的,简单的根据色差判断轮廓很可能不准确,其次知道了轮廓想要确定方块顶层区域也是很有难度的
所以我采用半自动方式,利用人确定终点位置,人为鼠标挪到终点右键一下,记录下终点坐标,简单粗暴就是累点
针对上述2:需要一个控件,每次起跳前读这里的数字
针对上述3:调用win32接口,鼠标移动至界面内,鼠标左键按下,线程休眠xx毫秒,鼠标左键松开
最终效果
具体实现
图像匹配
这里图像匹配指的是在一个大图A中找到小图B的位置,可能是多个或一个坐标,我之前并没有处理过图像相关,所以只能在网上看人家怎么实现的,在网上找了一个比较靠谱的例子,但他只找了单个匹配结果,我改成了找多个匹配结果,具体代码如下
1 | /// <summary> |
我改成匹配多个结果的时候用的方法是把匹配到结果图形右下角到坐标0,0的区域涂黑,然后重新匹配,直到没有结果为止。但是这个跳一跳不用匹配多个结果,他只要这个方法确定象棋位置就可以
鼠标钩子
这部分其实比较简单,就是调用 user32.dll 外部方法,搞几个委托处理下回调函数,有一个需要注意点就是钩子的回调函数必须搞成静态变量,不然会被GC回收掉,导致回调报错,我自己整理的钩子类如下
1 | /// <summary> |
界面以及主逻辑
因为每次跳动都要确定模拟器的区域,所以第一步我先获取句柄,然后根据窗体句柄获取模拟器界面边界,屏幕截图在截取出模拟器的界面,得到匹配用的原图
素材图片,就是旗子身体的一部分,因为根据模拟器窗体大小会变化,所以采用读取本件的方法,这意味着你要事先截取好素材图片,需要注意的是之前自己写的图片匹配方法比较死板,所以素材图片不能把背景搞进去,不然肯定匹配不出来
然后就是 user32一些外部方法,用来移动鼠标,模拟鼠标操作
1 |
|
user32部分
1 |
|
后记
- 效果图每次右键一次会记两次日志是因为我之前点了两次go按钮,导致每次右键回调了2次
- 跳一跳后台估计会根据连续perfect次数判断是否用作弊,如果它判断你作弊就不记录成绩了,而且我怀疑只要你超过一定分数他都直接判你作弊,然后骗一波个人照去申诉,因为作不作弊没那么容易区分
- 图像匹配和识别简单的很容易实现,但是想实现复杂一些的,比如扭曲倾斜的图片,没有研究过理论光靠直觉是想不出解决方案的,还是很有深度