跳一跳——电脑能做的事就不要人工来做啦
补发30日未发的博客。
PS:最新改进的算法和针对我自己手机调优的参数已经停不下来了,见项目:https://github.com/GameTerminator/AutoJump
几年前参考网上的文章写过天天连萌自动玩的项目(之前写在 iteye 的博客上:http://maosidiaoxian.iteye.com,github 项目地址为:https://github.com/GameTerminator/lianmeng),这次微信小游戏里的跳一跳玩了玩,就自然而然地想到用同样的方式来做。
经过几次修正和简化,最终思路和实现如下:
- 使用 monkeyrunner 里的接口截图
- 找出跳动的那个小球的 x 坐标
- 找出最终要跳达的点的 x 坐标
- 算出其距离,并按线性方程计算出时间
- 使用 monkeyrunner 里的接口模拟长按事件
接下来是完整的 Java 代码实现过程。
截图及模拟长按
要调用 monkeyrunner 来截图及模拟长按,我们需要 sdk 里的几个 jar 包,它们分别是(以下版本省略为*
):
- chimpchat-*.jar
- common-*.jar
- ddmlib-*.jar
- guava-*.jar
以上这些 jar
包在 sdk
中的 tools/lib/
中可以找到。然后我们使用其 API
来实现 ADB
连接,截图,长按。代码如下:
package com.githang.autojump;import com.android.chimpchat.adb.AdbBackend;
import com.android.chimpchat.core.IChimpDevice;
import com.android.chimpchat.core.IChimpImage;import java.awt.image.BufferedImage;/*** @author 黄浩杭 (huanghaohang@parkingwang.com)*/
public class AdbHelper {private final AdbBackend mAdbBackend = new AdbBackend();private IChimpDevice mChimpDevice;public void waitForConnection() {mChimpDevice = mAdbBackend.waitForConnection();}public void disconnect() {mChimpDevice.dispose();}/*** 截图*/public BufferedImage snapshot() {IChimpImage img;// 当尝试次数太多时不再尝试。int tryTimes = 0;do {System.out.println("截图中.." + tryTimes);img = mChimpDevice.takeSnapshot();tryTimes++;} while (img == null && tryTimes < 15);if (img == null) {throw new RuntimeException("try to much times to take snapshot but failed");}return img.getBufferedImage();}/*** 长按* @param x x坐标* @param y y坐标* @param ms 长按时间,单位毫秒*/public void press(int x, int y, int ms) {mChimpDevice.drag(x, y, x, y, 1, ms);}
}
上面的代码中,由于 IChimpDevice
没有直接提供长按的接口,这里使用的是拖拽方法。
找到起始位置
接下来是要找到跳跃的起始位置。这里我们简化一下,允许存在一些误差,找到小球的中心的 x
坐标,和目的点的 x
坐标即可。
由于在每一步中小球都不会有变化,并且在小球上面不会有其他色块与小球颜色接近,所以我想到的找到小球中心的 x
坐标的思路如下:
先获取小球的一部分图像,然后截图整个界面,由上至下遍历,找到与小球颜色接近的那块区域,其中心点就是小球的中心点。
截图小球的方式有多种,比如用 PS 抠图,或 QQ 截图,代码也可以,方式如下:
先截取游戏时的界面,然后用 PxCook 测量出小球的位置。我手机屏幕为720 * 1280
,截取的是小球中间的 24 * 24
的一块区域,代码如下:
private static void clipTarget() throws IOException {BufferedImage image = ImageIO.read(new File("screen.png"));BufferedImage target = new BufferedImage(24, 24, BufferedImage.TYPE_INT_ARGB);for (int i = 0; i < 24; i++) {for (int j = 0; j < 24; j++) {target.setRGB(i, j, image.getRGB(212 + i, 620 + j));}}ImageIO.write(target, "png", new File("target.png"));}
上面的 212
及 620
是在 PxCook 中测量出来的数值。
然后就是找出每一步小球所在的位置。思路也很简单,逐行往下遍历,如果某个像素点的颜色与刚才所获取的小球区域的颜色相近,则遍历这个点为起始点的[x,y][x+23, y+23]矩形区域,如果每个像素点都接近,则表示这块区域就是小球,否则则继续遍历。判断颜色相近,我想到的是其 R
G
B
相差均小于10。最终找到小球的代码如下:
private static boolean isJumpFrom(BufferedImage source, BufferedImage target, int x, int y) {for (int i = 0, width = target.getWidth(); i < width; i++) {for (int j = 0, height = target.getHeight(); j < height; j++) {int colorValue = target.getRGB(i, j);if (colorValue == 0) {continue;}int tempX = x + i;int tempY = y + j;Color targetColor = new Color(colorValue);Color sourceColor = new Color(source.getRGB(tempX, tempY));if (Math.abs(targetColor.getRed() - sourceColor.getRed()) > 10|| Math.abs(targetColor.getGreen() - sourceColor.getGreen()) > 10|| Math.abs(targetColor.getBlue() - sourceColor.getBlue()) > 10) {return false;}}}return true;}
从上往下逐行进行遍历,代码如下:
int width;
int height;
BufferedImage target = ImageIO.read(new File("target.png"));
int bWidth = target.getWidth();
int bHeight = target.getHeight();
while (true) {BufferedImage image = helper.snapshot();width = image.getWidth();height = image.getHeight();LOG.info("查找位置");int toX = findToX(width, height, image);FINDING:for (int y = height * 2 / 5, endY = height * 4 / 5; y < endY; y++) {for (int x = 0, endX = width - bWidth; x < endX; x++) {if (isJumpFrom(image, target, x, y)) {final int targetX = x + bWidth / 2;final int targetY = y + bHeight / 2;LOG.info("找到位置: " + targetX + ", " + targetY);final int distance = Math.abs(toX - targetX);final int time;// TODO 计算出时间helper.press(targetX, targetY, time);Thread.sleep(time);break FINDING;}}}
}
找出跳跃终点
在上面的代码中,有个 findToX(width, height, image)
方法的调用,它就是用于找出跳跃的终点坐标。它的原理也很简单。
由于在游戏中,背影是纯色渐变的,而要到达的区域,它的顶面颜色与背影色相差较大,并且不是椭圆就是菱形,它的特点是在这个平面上,中心点与顶点的 x
坐标相同。所以只要在显示分数的下面,从上往下每一行进行遍历,找到有一点与上面那一行的点颜色相差较大,这个点的 x
坐标就是要跳过去的点的 x
坐标了。代码如下:
private static int findToX(int width, int height, BufferedImage image) {for (int y = height / 5, endY = height / 2; y < endY; y++) {Color background = new Color(image.getRGB(2, y - 1));for ( int x = 0; x < width; x++) {Color color = new Color(image.getRGB(x, y));if (Math.abs(color.getRed() - background.getRed()) > 10|| Math.abs(color.getGreen() - background.getGreen()) > 10|| Math.abs(color.getBlue() - background.getBlue()) > 10) {LOG.info("跳到:" + x + ", " + y);return x;}}}throw new RuntimeException("ToX not found!");}
最终代码
最后是写一个大循环,每一步里面截图,找到要终点 x
坐标,找到小球中心,算出距离,再换算成时间,发送模拟按下事件,然后暂停按下的时间,再暂停 2 秒。这里暂停 2 秒的原因是,有些场景,停留 2 秒以上会有加分。最终 main
方法代码如下:
public static void main(String[] args) throws InterruptedException, IOException {AdbHelper helper = new AdbHelper();helper.waitForConnection();int width;int height;BufferedImage target = ImageIO.read(new File("target.png"));int bWidth = target.getWidth();int bHeight = target.getHeight();while (true) {BufferedImage image = helper.snapshot();width = image.getWidth();height = image.getHeight();LOG.info("查找位置");int toX = findToX(width, height, image);FINDING:for (int y = height * 2 / 5, endY = height * 4 / 5; y < endY; y++) {for (int x = 0, endX = width - bWidth; x < endX; x++) {if (isJumpFrom(image, target, x, y)) {final int targetX = x + bWidth / 2;final int targetY = y + bHeight / 2;LOG.info("找到位置: " + targetX + ", " + targetY);final int distance = Math.abs(toX - targetX);final int time;time = Math.max(330, (int) (distance * 2.38f));LOG.info("距离:" + distance + " 按下时间:" + time + "ms");helper.press(targetX, targetY, time);Thread.sleep(time);break FINDING;}}}Thread.sleep(2000);}}
其中由距离计算出时间的公式可以自己再进行调优。目前我的公式基本都能拿三四百分以上,最高是 800 多分。
项目完整代码,请参见 Github 项目:https://github.com/GameTerminator/AutoJump。Idea Gradle 项目。
其他相关项目:
- 天天连萌自动玩:https://github.com/GameTerminator/lianmeng
- 别踩白块儿暴力玩法:https://github.com/GameTerminator/dont-touch-white
排行榜:
在朋友里刷个第一名还是挺简单的。
跳一跳——电脑能做的事就不要人工来做啦相关推荐
- opencv在电脑屏幕上画_用Python+OpenCV让电脑帮你玩微信跳一跳
前言 最近微信小游戏跳一跳大热,自己也是中毒颇久,无奈手残最高分只拿到200分.无意间看到教你用Python来玩微信跳一跳一文,在电脑上利用adb驱动工具操作手机,详细的介绍以及如何安装adb驱动可以 ...
- 100行python代码做一个程序_100行python代码实现微信跳一跳辅助程序
写在前面 分享一下今天下午用python写的"跳一跳"小游戏的辅助程序.之前是准备用树莓派操控一个"机械手指"来代替人的触摸操作,但该方案还在酝酿中,实现了再分 ...
- scratch小游戏脚本大全_酷酷带你一起做小游戏--跳一跳
运用scratch我做了一个跳一跳小游戏,首先我要确定游戏流程, 小恐龙跑向障碍物,玩家用键盘的空格键控制恐龙跳跃 如果恐龙跳过障碍物则游戏分数加一 如果恐龙接触到障碍物则游戏结束,脚本全部停止 先添 ...
- python做的游戏怎么导到微信_微信跳一跳游戏的脚本-scratch导出到微信-微信小程序是怎么做的...
1. 微信更新后出来了一块比较火的小游戏,要是一款不涉及到排行的游戏,可能没人去关注这款游戏.最开自己一直苦练技术,想在微信排行上面装一装,练了好久才跑三百多分.接着在Github(Github地址: ...
- python做的游戏放到微信_【1、 创建一个python的文件,运行后,文字版方式模拟微信游戏“跳一跳?】...
python脚本学习过程推荐 学习流程: 一:打础 1.找到合适的书籍(推荐Python核心编程2Dive into Python),大致读一次,循环啊判,常用类啊,搞懂(太难的跳过) 2.勤练习py ...
- 做一个微信跳一跳的外挂
淘宝上好多卖跳一跳代练的,其实做一个很简单,不需要有安卓开发知识,不需要有图像识别知识,不需要有人工智能知识!重要的事情说三遍,都不需要. 简单说一下思路: 1.用adb连手机截图,命令是: adb ...
- 手把手教你做跳一跳助手
转载自:http://blog.csdn.net/OQjya206rsQ71/article/details/78970088 其实也不能说算是外挂吧,算是个游戏小助手吧,毕竟不能抓包,也不能直接修改 ...
- “跳一跳”小游戏这么火爆,它是如何做的设计和开发?
2018 伊始,最火爆的不是春晚和红包,而是从天而降的"跳一跳".这款来自微信的轻量级小游戏,以 2800 万人 / 小时的惊人 PCU 数据,稳据小游戏排行榜首位.如果你还不了解 ...
- 糖葫芦不做了,我们来跳一跳吧 O(∩_∩)O~~ PCA + 截断 SVD (含 python 实现及代码细节梳理)
上一篇我串了糖葫芦,矩阵乘法/线性变换 + 特征分解/奇异值分解(SVD) + PCA. PCA 本来是糖葫芦的最后也是最上面那颗山楂,无奈山楂太大了 2333,所以这里另起一篇了.然后 PCA 这篇 ...
最新文章
- 通过BeanShell获取UUID并将参数传递给Jmeter
- CCF C³:创业公司如何面对开源?知乎CTO李大海:谢邀
- hdu1316 大数
- c语言词法分析程序实验报告,实验一词法分析程序设计与实现
- /etc/passwd 与 /etc/shadow文件的区别
- #pragma pack(n)和sizeof求结构的大小
- java命令行参数工具_Java方法中的参数太多,第8部分:工具
- IDEA 配置Maven国内源
- c++ opencv mat_实战 | OpenCV 实现多张图像拼接
- Flink-org.apache.flink.streaming.api.windowing.windows.Window
- SQLServer中在视图上使用索引(转载)
- Dev Express 安装
- 超强 | 保险单据在线OCR,秒速识别保单信息
- VirtualBox下安装Windows Server 2008
- 安装microsoft office 和visio遇到的那些事儿
- 什么是激光导航扫地机器人?
- RTI_DDS使用参与者QoS属性编辑传输TCP
- 批量安装windows系统补丁包
- ArcGIS之经纬度表格数据转矢量
- 【毕业设计选题】2022通信工程毕业设计题目推荐大全