本
文
摘
要
大家好我是萝卜君
最近
微信「跳一跳」火了
不仅火了游戏
还火了程序员
网上脑洞大开的玩法层出不穷
大家都献上了自己的高分秘籍
最早出现的——手工测量法:
鼠标测距、软件自动弹射法:
机械臂氪金法:
主子亲自上手法:
但这些玩法
我们都看不上
因为
手工测量太原始了
软件外挂体现不出技术性(不够装比)
氪金方法…我还要留着钱养李泽言
至于主子法
本萝卜还没有喵
所以,今天
我要介绍一种即省钱又足够装比的方法!
不需要氪金、不需要双手
就可以轻松破万分
赢得妹子们崇拜的目光
机械+电控+视觉全自动物理外挂
还附有详细教程和下载资料哦
萝卜君教你「跳一跳」破万分现在本萝卜来教大家,具体如何制作。步骤主要分为三部分,机械搭框架,视觉识别游戏界面和电控控制触摸笔按压。
整个实现逻辑是:数据线将手机画面传输给 PC,PC 通过算法处理识别出目标点,再测量出跳跃的距离,从而计算出屏幕按压时间,最后通过串口传输给主控电路板,主控电路板根据该时间精准控制触摸笔按压手机,实现小人跳跃。
PART 1:机械
我们要搭建基本平台,连接所有线路。根据需求选定一些基本的材料:能进行准确位置控制的 RoboMaster M3508 电机+C620 电调+固定座、棉签+锡箔纸(制作触摸笔)、RoboMaster 主控板、电池、遥控器、数据线、信号线、手机、电脑(linux)、摄像头、热熔胶枪等。
部分装备步骤
将电机、电调、手机、主控板按照一定位置固定在机架上。 制作简易触摸笔:棉签一端沾水,将导线拨开连接在棉签头上,用锡箔纸包住,制作完成。将触摸笔固定在电机轴的输出处,导线另一端和主控板 GND 相连,此时触摸笔即可使用。(原理在后面会讲)按照顺序接线:手机 USB(打开 MTP 模式)和 USB 转串口模块一起连接到 USB 分线器上,然后接入电脑。搭建完毕PART 2:视觉识别
外挂小平台就搭建完成啦,现在要识别方块距离,判断需要跳多远。我们的思路是:通过 adb 获取手机截图→传输到电脑→找到自己的位置→找到目标方块的位置→根据两个位置,计算距离,换算时间。
1. 获取截图
电脑通过 adb 工具给手机发送截图指令,截取当前游戏画面并保存到手机。(电脑需要安装 adb 驱动) 电脑通过 adb 工具发送拉取文件指令,将上一步截取的游戏画面拉取到电脑。2. 找到自己(棋子)的位置
因为小棋子的样貌不变,而且与所有方块和背景颜色差异明显,所以我们直接用颜色对图像进行分割。我们使用 color_test 得到了目标颜色的范围。
根据得到的颜色范围使用 cv2.inrange() 函数(二值化)对图片进行颜色的分割,像素值在范围内的图像被标记为白色,范围外的为黑色,这样就可以找到自己的位置了。
二值化学习传送门:《二值化图像切割,让机器人视觉识别变得简单高效》
棋子的像素被标记为白色关键代码:
color_lower=np.int32([105,25,45]) color_upper=np.int32([135,125,130]) color_mask = cv2.inRange(hsv_img, color_lower, color_upper) color_mask = open_op(color_mask) #开操作 color_mask = close_op_large(color_mask) #闭操作然后使用开操作去掉图像中的噪点,使用闭操作把棋子的头和身子连起来。
接着找到面积最大的连通域(白色部分),将矩形的底部中心点设定为自己的位置,也就是图中绿点的位置。
3. 找到目标(方块)的方块
游戏背景是接近纯色的,而且有平滑的过度,所以通过提取边缘的方式找目标是最方便的。因为跳出的角度永远一致,所以只要知道棋子和目标的 x 坐标,计算出两点的横向距离,就可以知道要按多久了。想要找到 x 坐标,只需要找到目标的最高点,因为这个点一定过中心线,也就能知道目标的 x 坐标了。
下面来操作吧~
我们首先确定方块的大概范围,可以根据棋子的位置确定。如果棋子偏右,我们就到左边去找方块,目标范围就是绿框的位置。
通过 sobel 算子提取边缘,因为边缘横向的分量居多,所以使用检测横线的 sobel 算子提取边缘。之后经过 sobel 算子的图像进行二值化操作,滤掉一些不强的边缘的干扰。
因为背景的颜色和目标颜色有些时候看起来比较接近,所以我们对 HSV 三个通道各个通道都做了上面的提取边缘的处理,随后把三张图片按位取或,就可以得到稳定的边缘。
关键代码:
edge_region_list=[] for idx in xrange(3): region_gray=cv2.cvtColor(region,cv2.COLOR_BGR2HSV)[:,:,idx] #分别取HSV中不同的通道 region_shape=region.shape region_gray=cv2.GaussianBlur(region_gray,(5,5),0) #高斯平滑 region_sobel = np.abs(cv2.Sobel(region_gray,cv2.CV_32F,0,1,ksize=3)) #sobel算子提取边缘, region_sobel=np.uint8(region_sobel) region_sobel=cv2.threshold(region_sobel,12,255,cv2.THRESH_BINARY)[1] #二值化滤掉不强的边缘的干扰 region_sobel=open_op(region_sobel) #开操作去噪 region_sobel=close_op_large(region_sobel) #闭操作把一些不连续的边缘点连起来 region_sobel=np.uint8(region_sobel) edge_region_list.append(region_sobel) region_sobel_final=np.bitwise_or(edge_region_list[0],edge_region_list[1]) region_sobel_final=np.bitwise_or(region_sobel_final,edge_region_list[2]) #将HSV三个通道得到的边缘按位取或得到边缘之后,找到边缘中最上边的点,就可以确定目标最上的点的位置。棋子总是以 30 度的角度条跳跃,我们根据棋子的位置和目标最高点的 x 坐标,就可以计算出目标块的中心点的 y 坐标了。
4. 计算距离和时间
前面说过,我们需要知道棋子和目标的 x 坐标距离,距离和需要按屏幕的时间呈线性关系,这个关系只要通过几次实验就可以得到了。通过线性关系计算出按压时间,再将时间通过串口发送给主控,从而控制电机按压时长。(相关代码可下载查看)
PART 3:电控
接下来我们进入代码调试环节,目的是让 PC 将识别出来的结果告诉单片机,单片机再以一定的规则控制电机转动。
为了方便调试,我们增加一个工具——遥控器。其实用一个开关也可以实现同样功能,但是用遥控器看起来比较帅。
触屏如何实现
手机是电容触摸屏,所以我们用导体挤压,使电容变化来达到触屏效果。用棉签头包上锡箔纸,保持棉签头的湿润,有导线连接到主控板的地线,就可以模拟人体的低电势导体特性了。
单片机与 PC 通信
我们需要制定一个与 PC 之间通信的数据包协议,这里使用串口通信(USB 转 TTL)。
通信的数据包协议:相当于两个国家的哑巴需要交流,需要用一种国际手语来对话,这种国际手语就是协议。
我们实际需要的数据只有中间的“time”,但为了保证数据正确,我们加入了帧头帧尾的校验部分。
单片机控制电机转动
我们要设定电机需要走的行程。把 M3508 电机转一圈分成 8192 格(格数是电机特性决定的),大约需要转 4-5 度,也就是转 91-113 格。减速箱比例大约是 1:19(勤勤恳恳转了 19 格,结果被减速成 1 格),所以大约需要勤勤恳恳转 2000 格,竹签就可以转 4-5 度了。
因为按压屏幕需要一定的力,所以设定的目标位置应该在屏幕位置以下。
控制角度
控制它转起来如何有计划地转
我们需要考虑一下具体的控制流程,并设计一个合适的状态机,让电机按照我们的规则转动:
状态机简单说就是,我们可以根据目前所处在的状态,来判断等会要做什么,对什么情景条件会产生什么反应,满足什么条件后转移到下一步,或者到前面的某一步,形成循环。
具体的代码可以下载查看,以下是准备就绪状态。
遥控器接收
遥控器接收也需要相关代码,感兴趣的同学可以下载代码查看,没有条件用遥控器的同学可以用小开关达到相同的效果。
最后启动游戏,去美美地睡一觉,醒来就可以欣赏分数 *** 排行榜啦!
最后说两句
想要称霸排行榜,还要很多更好更快的方法,几乎所有只需要一只手和一双眼的小游戏,都可以用同类型外挂绿色。但教程只是以技术交流为目的,让大家了解更多技术知识,如果只是为了刷分而做了外挂,那萝卜君敬你是条汉子!
留个小作业
用同类型方法做个「别踩白块」的物理外挂吧~制作成功的小伙伴把视频发给萝卜君,可以在下一期上墙哦~