跳一跳小外挂(附完整代码)
![](/assets/blank.gif)
1实验环境
操作系统:Windows10
编码语言:Python3.6
编译平台:Pycharm
Python库:os、datetime、matplotlib、opencv-python、time
2实验代码流程图
3代码运行步骤和结果等
3.1 手机和电脑用数据线连接
使用通过数据线连接手机,将开发者模式打开并授权
通过adb命令
adb devices |
可以查看连接的Android设备的信息
3.2 获取手机相关的信息
查看Android手机的分辨率(第四行)
adb shell dumpsys window displays |
获取屏幕密度
adb shell wm density |
获取手机型号
adb shell getprop ro.product.device |
获取Android系统的版本
adb shell getprop ro.build.version.release |
3.3 截屏
输入如下命令:
adb shell screencap -p /sdcard/auto.png |
此时,截屏的图片就保存到 /sdcard/auto.png文件中。
注意:/sdcard/和/data/目录是可以写入的。
可以通过命令查看sdcard目录下所有的文件。
adb shell ls /sdcard/ -l |
通过如下命令把手机上的文件拷贝到电脑上
adb pull /sdcard/auto.png h:\ |
此时,图片就会被拷贝到h:\根目录下了。打开即可看到当前手机的屏幕信息。
3.4 屏幕点击事件
通过如下命令模拟手机的滑动事件
adb shell input swipe x1 y1 x2 y2 duration |
通过adb shell input swipe命令进行滑动
l x1、y1:滑动开始的点。
l x2、y2:滑动结束的点。
l duration:持续的时间(单位ms)。
特殊情况下:如果不写duration参数,就理解为点击事件。如果写duration,然后x1y1和x2y2是相同的点,就表示长按。
跳一跳关键是:duration的值的计算。
尝试:
adb shell input swipe 100 100 100 100 700 |
尝试修改duration的值,看看跳的效果。
求得可以拿到加分的中间值。比如555~871都可以拿到加分(555以下和871以上就不能拿到加分),此时则取中间值为(555+871)/2=713 作为后面计算的参考值。
3.5 duration值的计算
假设我们截屏的效果是如下:
从图中可以看到,时间的值跟开始位置到结束位置的距离有关。
假设时间是t,距离是s。公式应该是s = at
基本思路:两点之间的距离乘以一个时间系数。
所以要从截图上识别出起跳位置的坐标(x1,y1)和目标位置的坐标(x2,y2)。
起跳位置的坐标:小人的底座中心点
目标位置的坐标:目标菱形的中心点
然后计算这两点之间的距离(欧氏距离):sqrt((x1-x2)2+(y1-y2)2)
3.6 寻找关键坐标——起跳坐标
算法策略:获取小人的底座中心点的值作为起跳点。
1 获取小人的所有像素点中y坐标的最大值
2 在小人y坐标的最大值那些像素点中,计算出x的平均值,作为小人底座的x的值。
3 y坐标的最大值减去一个偏移值,就作为小人底座的y值。(注意:该偏移值不同的设备是不同的,同一台设备不同场景下是一样的)
比如教师机的设备中最低点的值是(410,1162),中心值是(410,1142),从而计算出偏移值为1162-1142=20
3.7 获取目标坐标的y值
取屏幕宽和高的一半(x=540和y=960)
我们会发现,目标格子的边沿(x=560,y=980)和这个是差不多的(y的偏差是20,x的偏差是20)
以后每次跳动的时候,假如已经知道目标格子的边沿,和目标坐标的x值,就可以很轻松计算出目标坐标的y值。
注意:每个格子的宽和高的比例是相同的。
方形:左:(560,848) 园:左:(251,876)
右:(1015,848) 右:(522,876)
上:(790,718) 上:(388,799)
下:(790,980) 下:(388,957)
中:(790,850) 中:(388,876)
高和宽的比例:(980-718)/(1015-560) =262/455=0.576。假设该值为p
最后,由已知的目标坐标的x值,求目标坐标的y值。
先附上运行结果,以及截图信息:
在理解了跳一跳的基本思路之后,现在附上完整代码(有注释):
# main.py# _*_ coding:utf-8 _*_ __author__ = 'WoLykos'from operations import * from draw import * from algorithm import * import time import random# 测试截屏 # def test_screen_cap(): # op = Operation() # op.screen_cap()# 测试显示图片 def test_show_pic():draw = Draw()draw.show_pic("img/auto.png")# 测试计算欧式距离 def test_euclidean_distance():algorithm = Algorithm()p1 = (3, 4)p2 = (6, 8)d = algorithm.euclidean_distance(p1, p2)print(d)# 测试寻找关键坐标 def test_find_point():op = Operation()im = op.screen_cap()algorithm = Algorithm()start_x, start_y, end_x, end_y = algorithm.find_point(im)print("start_point:", start_x, start_y)print("end_point:", end_x, end_y)start_point = (start_x, start_y)end_point = (end_x, end_y)distance = algorithm.euclidean_distance(start_point, end_point)# print(distance)press_time = algorithm.distance_to_time(distance)op.jump(start_point, end_point, press_time)if __name__ == "__main__":# test_screen_cap()# test_show_pic()while True:# test_euclidean_distance() test_find_point()time.sleep(1 + 2*random.random())
# algorithm.py # _*_ coding:utf-8 _*_ __author__ = 'WoLykos'class Algorithm:# 构造器def __int__(self):pass# 计算两点之间的欧氏距离# p1和p2表示两个点 用元组来表示def euclidean_distance(self, p1, p2):return ((p1[0]-p2[0])**2+(p1[1]-p2[1])**2)**0.5 # ((p1[0]-p2[0])**2+(p1[1]-p2[1])**2)**0.5# 寻找关键坐标# 返回值1,2 piece_x, piece_y 起跳点的坐标 170,555# 返回值3,4 board_x, board_y 目标点的坐标 395,425def find_point(self, im):# piece_x = piece_y = 0# board_x = board_y = 0# 图像的大小w, h = im.size # (1080,1920)# 加载图像im_pixel = im.load()# 记录小人所有的点points = []# 记录y的最大值piece_y_max = 0# 1 计算出起跳点 就是小人底座的中心点# 1.1 获取小人的所有像素点中y坐标的最大值# 遍历图像中的每一个点# 遍历每一行for i in range(h // 3, h * 2 // 3):# 遍历每一列for j in range(w):pixel = im_pixel[j, i]# print("i = ", i, ",j = ", j, "pixel = ", pixel)# 判断pixel是否小人所在的位置# 当该点的RGB值约为56,56,82的时候就可以认为是小人所在的像素点了if (51 < pixel[0] < 61 and 51 < pixel[1] < 61 and 72 < pixel[2] < 102):# 把当前的点添加到points数组中points.append((j, i)) # (x,y)# 记录下y的值if i > piece_y_max:piece_y_max = i# print("piece_y_max = %d" % (piece_y_max,))# 1.2 在小人y坐标的最大值那些像素点中,计算出x的平均值,作为小人底座的x的值。bottom_x = []for x, y in points:if y == piece_y_max:bottom_x.append(x)piece_x = sum(bottom_x) // len(bottom_x)# print("piece_x = %d" % (piece_x,))# 1.3 y坐标的最大值减去一个偏移值,就作为小人底座的y值。(注意:该偏移值不同的设备是不同的,同一台设备不同场景下是一样的)piece_y = piece_y_max - 20 # 偏移值1130-110=20# print("piece_y = %d" % (piece_y,))# 2计算 目标格子的中心点# 2.1计算目标格子的x值points = []# 只取中间1/3进行扫描for i in range(h // 3, h * 2 // 3):if len(points) > 0:break# 取坐标的一个点作为背景的参照物last_pixel = im_pixel[0, i]# 逐个扫描右边的点for j in range(w):pixel = im_pixel[j, i]# 把当前点与最左边的点比较 如果RGB差异比较大 则认为是目标点# 排除该点为小人像素点56,56,82的可能性,BUGif not (54 < pixel[0] < 141 and 54 < pixel[1] < 130 and 69 < pixel[2] < 172):if (abs(pixel[0] - last_pixel[0]) + abs(pixel[1] - last_pixel[1])+ abs(pixel[2] - last_pixel[2]) > 10):points.append((j, i))top_x = []for x, y in points:top_x.append(x)board_x = sum(top_x) // len(top_x)# print("board_x = %d" % (board_x,))# 2.2计算目标格式子y值# 屏幕中心的值center_x = w / 2 + 20 # x的偏差是20center_y = h / 2 + 20 # y的偏差是20,园# 格子高和宽的比例height_per_width = 262 / 455# 计算出目标格子的y值(需要转换成整数)# 从piece_x调到board_x 如果piece_x < board_x则表示从左往右跳# 如果piece_x > board_x 则表示从右往左跳if piece_x < board_x:board_y = int(center_y - height_per_width * (board_x - center_x))else: # 从右往左跳board_y = int(center_y + height_per_width * (board_x - center_x))# print("board_y = %d" % (board_y,))return piece_x, piece_y, board_x, board_y# 距离与时间的转换def distance_to_time(self, distance):# 当0分的时候 距离为 527.5234591939964 时间为713p = 713 / 527.5234591939964 # 该算法后面待优化press_time = distance * preturn press_time
# operations.py # _*_ coding:utf-8 _*_ __author__ = 'WoLykos'import os import datetimefrom PIL import Image# 实现控制安卓 class Operation:# 构造方法def __int__(self):pass# 截屏def screen_cap(self):filename = time = datetime.datetime.now().strftime("%H%M%S")+".png"# 截屏并保存到手机cmd = "adb shell screencap -p /sdcard/auto.png"os.system(cmd)# 拷贝到电脑cmd = "adb pull /sdcard/auto.png "+"img/"+filenameos.system(cmd)# 打开图像文件return Image.open("img/"+filename)# 控制屏幕进行跳动def jump(self, src, dst, press_time):# print(press_time)press_time = int(press_time)cmd = "adb shell input swipe %d %d %d %d %d" % (int(src[0]), int(src[1]),int(dst[0]), int(dst[1]),press_time)print(cmd)os.system(cmd)
大功告成!!
谢谢各位。。
转载于:https://www.cnblogs.com/WoLykos/p/9241448.html
跳一跳小外挂(附完整代码)相关推荐
- 基于汇编实现的欢乐QQ堂小游戏 附完整代码
本次实现制作了汇编版的QQ堂,使用了VGA 320x200 256色视频显示, FAT12文件系统.时钟中断,nasm + gcc联合编译,通过端口设置调色板.其中除了AI,游戏界面.逻辑等均由汇编实 ...
- 毕业设计:基于汇编实现的欢乐QQ堂小游戏 附完整代码
本次实现制作了汇编版的QQ堂,使用了VGA 320x200 256色视频显示, FAT12文件系统.时钟中断,nasm + gcc联合编译,通过端口设置调色板.其中除了AI,游戏界面.逻辑等均由汇编实 ...
- html页面数字滚动,Vue.js大屏可视化数据数字滚动翻转跳转效果(通俗易懂附完整代码)...
原文:Vue.js大屏可视化数据数字滚动翻转跳转效果(通俗易懂附完整代码) 大屏数字滚动翻转效果来源于最近工作中element后台管理页面一张大屏的UI图,该UI图上有一个模块需要有数字往上翻动的效果 ...
- php跳一跳小游戏,原生JS实现的跳一跳小游戏完整实例
本文实例讲述了原生JS实现的跳一跳小游戏.分享给大家供大家参考,具体如下: 以下说的是闲暇编写的一个小游戏--跳一跳,类似于微信的跳一跳,大体实现功能有: 1.先随机生成地图: 2.按住按钮释放后完成 ...
- html实现跳跳棋游戏,原生JS实现的跳一跳小游戏完整实例
本文实例讲述了原生JS实现的跳一跳小游戏.分享给大家供大家参考,具体如下: 以下说的是闲暇编写的一个小游戏--跳一跳,类似于微信的跳一跳,大体实现功能有: 1.先随机生成地图: 2.按住按钮释放后完成 ...
- Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(一)
Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(一) 本文目录: 一.[旋转的精灵女孩]案例运行效果 二.Three.js简介 三.Three.js代码正常运行显示条件 (1)不载入 ...
- 当微信遇上 10 万战绩的「跳一跳」外挂,程序员还能“逍遥”多久?
点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 一款热门游戏,普通用户玩的是乐趣,而对于程序员来说,走的是非常人之路,以各种花样技术方法获取 ...
- H5版仿制微信跳一跳小游戏,网页版仿微信跳一跳小游戏源码,实现了跳一跳的基本核心功能
H5版仿制微信跳一跳小游戏,网页版仿微信跳一跳小游戏源码,实现了跳一跳的基本核心功能 完整代码下载地址:H5版仿制微信跳一跳小游戏,网页版仿微信跳一跳小游戏源码 运行截图 Project setup ...
- Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(三)
Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(三) 本篇目录: 六.完整构建整个[旋转的精灵女孩]实例 (1).新建.启动webGL工程空间 (2).构建项目的目录层次结构 (2. ...
最新文章
- 计算机与材料成型与控制方面的应用,广东科技学院
- 小玩流媒体播放——HLS流媒体点播系统
- Codeforces 833B 题解(DP+线段树)
- Android GIS开发系列-- 入门季(11) Callout气泡的显示
- boost::mp11::mp_set_push_back相关用法的测试程序
- 计算机用的机械硬盘的工作原理,为啥一震就坏?机械硬盘的构造原理是什么?...
- apache mesos_Apache Mesos:编写自己的分布式框架
- 业内首款云原生技术中台产品云原生 Stack 来了
- hibernate mysql 读写分离_SpringBoot集成Spring Data JPA及读写分离
- 企业微信登陆服务器设置,企业微信怎么登入
- saltstackmysql return报错
- 内涵社区APP,一款集内涵段子,百思不得其姐,煎蛋于一身的搞笑社区
- 域名解析ip地址的过程
- 在vue项目中使用阿里云播放器
- TOM企业邮箱注册流程是什么,如何开通邮箱
- 【Linux】Ubuntu 20.04 wifi 问号连接不上解决方法
- 祥云杯2022 writeup
- 苹果手机如何用短信信息服务器,Iphone双卡双待如何发信息? 苹果双卡手机发短信的方法...
- IIS上解决ASP.Net第一次访问慢的处理
- GSMA宣布了首批2017世界移动大会-上海主题演讲嘉宾名单