Java代码模拟按键玩Android微信跳一跳

微信跳一跳这个小游戏很火,网上已经出现了很多“辅助”,大部分都可以让你拿高分,常年稳置榜首,9999分不是梦。

我出于兴趣,使用Java也写了一个,只能在Android上玩,我写这个不是为了拿高分,测试的时候是离线下测试的,就是想写来玩一玩。

大概思路如下:

  1. 电脑通过数据线连接手机。
  2. 通过 adb shell screencap -p /*.* 让手机截屏并保存到SD卡。
  3. 使用 adb pull /sdcard/*.* *://*.* 把手机里的图片拉取到电脑。
  4. 分析得到的图片从而计算模拟按键时间。

分析图片

       看这张图片,我们需要找到两个来确定跳跃的距离,第一个点是人物脚下的点,第二个点是目标跳板的中点。

       我直接遍历这张图的每一个像素点,但有点地方是可以忽略的,如上面的1/3和下面的1/3区域。

 

 

 



人物的点很好找,用PS打开图片,放大再放大


查看中间点的rgb值,一般都可以较准确的找到人物的中点,但有极少数情况会找不到。

 


       而目标跳板的中点就有点麻烦了,跳板的形状有正方形,圆形,我们可以找到两个点来确定跳板的中点,最上面和最下面的点。

       手机屏幕的坐标左上角为(0,0),从上到下,从右到左遍历图片,把遍历的每一个点的rgb值和背景(同一行最左或最右的像素点,因为背景色会从上到下渐变)比较,如果和背景色不同,那么目标的最上点就找到了。

接着找最下点,因为最上点已知了,最下点的查找范围就设置在最上点的左右,用同样方法即可找到。

取上下两点的中间就是目标跳板的中点了。


最后计算人物到目标跳板的距离


使用公式即可。

最后模拟按键时间通过使用距离乘上一个常熟得到,常数是多少,不知道,多试几下可以大概猜出,我用的是1.436 。


这个代码还不完美,只能玩400分左右。。。有时又能700分,不过,毕竟是自己写的,没法和GitHub上热门的比,已经较满意了,看心情决定要不要继续写,哈哈。


代码:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;

public class Main {
	
	private static int image = 0;
	
	public static void main(String[] args) throws Exception {
		while (true) {
			//截图到手机
			cmd("adb shell screencap -p /sdcard/.a/" + image + ".png");
			//从手机拉取图片到电脑
			new File("e:/" + image + ".png").createNewFile();
			cmd("adb pull /sdcard/.a/" + image +".png " + "e:/" + image + ".png");
			//计算按键时间并模拟按键
			int pressTime = (int) (get_pressTime()*1000/1000);
			cmd("adb shell input swipe 550 1600 550 1600 " + pressTime);
			System.out.println("按键时间为:"+pressTime);
			System.out.println("-----------");
			
			//模拟右滑
			//cmd("adb shell input swipe 850 1600 550 1600 400");
			image++;
			TimeUnit.MILLISECONDS.sleep(1000);
		}
	}
	
	//计算按键时间
	private static double get_pressTime() throws IOException {
		File file = new File("e:/" + image + ".png");
		BufferedImage img = ImageIO.read(file);
		int width = img.getWidth();
		int height = img.getHeight();
		
		int[] s = s_xy(img, width, height);
		if (s == null) {
			System.out.println("游戏结束!");
			System.exit(0);
		}
		//cmd("adb shell input swipe " +s[0]+" "+s[1]+" "+s[0]+" "+s[1]+" 2000");
		
		System.out.println("人的位置:" + s[0] + " " + s[1]);
		
		int[] o = o_xy(img, width, height);
		if (o == null) {
			System.out.println("游戏结束!");
			System.exit(0);
		}
		//cmd("adb shell input swipe " +o[0]+" "+o[1]+" "+o[0]+" "+o[1]+" 2000");
		System.out.println("目标垫子:" + o[0] + " " + o[1]);
		
		double d = Math.sqrt(Math.abs((o[0]-s[0]) * (o[0]-s[0]) + (o[1]-s[1]) * (o[1]-s[1])));
		System.out.println("两点距离:" + d);
		
		img.flush();
		return d * 1.436;
	}
	
	//寻找人的位置
	private static int[] s_xy(BufferedImage img, int width, int height) {
		int[] s = { 0, 0 };
		for (int y = height/3; y < height - height/3; y++) {
			for (int x = width/5; x < width; x++) {
				int rgb = img.getRGB(x, y);
				int r =(rgb & 0xff0000 ) >> 16 ;
				int g= (rgb & 0xff00 ) >> 8 ;
				int b= (rgb & 0xff );
				if (r == 57 && g == 59 && b == 102) {//脚底的rgb
					s[0] = x;
					s[1] = y;
					return s;
				}
			}
		}
		return null;
	}
	
	//寻找目标跳板中点
	private static int[] o_xy(BufferedImage img, int width, int height) {
		int[] o = { 0, 0 };
		for (int y = height/3; y < height-height/3; y++) {
			for (int x = width-2; x > 0; x--) {
				//右边对比点
				int trgb = img.getRGB(width-1, y);
				int tr = (trgb & 0xff0000) >> 16 ;
				int tg = (trgb & 0xff00) >> 8 ;
				int tb = (trgb & 0xff);
				
				//当前点
				int rgb = img.getRGB(x, y);
				int r = (rgb & 0xff0000) >> 16 ;
				int g = (rgb & 0xff00) >> 8 ;
				int b = (rgb & 0xff);
				
				//人头挡住
				if ((r <= 75 && r >= 50) && (g <= 76 && g >= 50) && (b <= 109 && b >= 50) && x >= 70) {
					//跳到人头左边
					x = x - 70;
					rgb = img.getRGB(x, y);
					r = (rgb & 0xff0000) >> 16 ;
					g = (rgb & 0xff00) >> 8 ;
					b = (rgb & 0xff);
				}
				
				//找到跳板的最上点,和背景的rgb值做对比,加点误差范围
				if ((r <= tr-3 || r >= tr+3) && (g <= tg-3 || g >= tg+3) && (b <= tb-4 || b >= tb+3) || 
					(r <= tr-3 || r >= tr+3) || (g <= tg-3 || g >= tg+3) && (b <= tb-4 || b >= tb+3) || 
					(g <= tg-3 || g >= tg+3) || (b <= tb-3 || b >= tb+3) && (r <= tr-4 || r >= tr+3))
				{
					
					/*
					o[0] = x;
					o[1] = y;
					return o;*/
					//药瓶
					if (rgb == img.getRGB(x-5, y) && r == 255 && g == 255 & b == 255) {
						x -= 5;
						for (int by = y + 60; by > y; by--) {
							for (int bx = x + 30; bx > x - 30; bx--) {
								if (img.getRGB(bx, by) == rgb) {
									o[0] = (x + bx)/2;
									o[1] = (y + by)/2;
									return o;
								}
							}
						}
					}
					//正方形跳板  找最下的点
					for (int by = y + 260; by > y; by--) {
						for (int bx = x + 60; bx > x - 60; bx--) {
							if (img.getRGB(bx, by) == rgb) {
								o[0] = (x + bx)/2;
								o[1] = (y + by)/2;
								return o;
							}
						}
					}
				}
			}
		}
		return null;
	}
	
	//调用命令行
	private static void cmd(String command) {
		Process process = null;
		try {
			process = Runtime.getRuntime().exec(command);
			process.waitFor();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			if (process != null) process.destroy();
		}
	}
}

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值