一、前言:

前段时间微信更新了新版本后,带来的一款H5小游戏“跳一跳”在各朋友圈里又火了起来,类似以前的“打飞机”游戏,这游戏玩法简单,但加上了积分排名功能后,却成了“装逼”的地方,于是很多人花钱花时间的刷积分抢排名。后来越来越多的聪明的“程序哥们”弄出了不同方式不同花样的跳一跳助手(外挂?),有用JS实现的、有JAVA实现的、有Python实现的,有直接物理模式的、有机械化的、有量尺子的等等,简直是百花齐放啊……

赶一下潮流,刚好有点时间,于是花了一个下午时间,我也弄了一个C#版本的简单实现。

二、实现:

简单的实现流程: 连接手机 -> 获取跳一跳游戏界面 -> 获取位置(棋子位置和要跳跃的落脚点位置) -> 点击棋子跳跃

1、连接手机

电脑要连接并操作安卓手机,一般是通过ADB协议连接手机并进行操作。连接手机前要求手机已开启USB调试模式,可通过USB线或者TCP方式连接手机。正常只要电脑安装了adb sdk tools之类的工具包,就会自带有adb命令,所以C#要能操作手机,简单实现就是直接利用现成的adb命令。

手机通过USB线接入电脑后,在CMD窗口输入以下adb devices命令,如果显示有device列表则表示手机已连接成功可以对手机进行操作了。

C:\Users\k>adb devices
List of devices attached
e832acb device

  

2、获取游戏界面

获取手机界面的截图可通过以下adb命令获取:

adb shell screencap -p [filename] 

参数 :

- p 表示截图保存格式为PNG图像格式。

filename: 截图保存的路径地址(手机路径),如果不输入则将截图数据直接输出到当前控制台会话,否则会将截图保存到相关路径地址(必须有写权限)

为避免文件保存到手机后还要再执行adb pull(拉文件到本地电脑)的操作,所以选择不带filename参数的命令。在C#代码里通过Process这个类进行adb命令的调用执行,实现代码如下:

var startInfo = new ProcessStartInfo("adb", "shell screencap -p");
startInfo.CreateNoWindow = true;
startInfo.ErrorDialog = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
var process = Process.Start(startInfo);
process.Start();
var memoStream = new MemoryStream();
process.StandardOutput.BaseStream.CopyTo(memoStream);

但由于adb client的原因,在它输出的截图数据流中会对'\n'(0A)这个字符替换为''\r\n'(0D0A)这两个字符,并且在测试中还发现不同的手机替换次数还不相同的,有可能替换一次,也有可能替换二次!所以为解决这个问题,先计算在最开始的10字节里的数据出现了多少次'\r'(0D)字符后再出现‘\n'(0A)字符,因为正常的PNG文件,在文件头的第4,第5个字节位置里会有'\r\n'(0D0A)标志,所以检查出来的出现次数就表示'\n'(0A)被adb client替换了多少次,之后再对整个接收到的数据流进行'\n'(0A)还原(删除无用的'\r'(0D)字符)。

>>统计'\n'被替换了次

        private static int Find0DCount(MemoryStream stream)
{
int count = ;
stream.Position = ;
while(stream.Position < && stream.Position < stream.Length)
{
int b = stream.ReadByte();
if(b == '\r')
{
count++;
}
else if(b == '\n')
{
return count;
}else if(count > )
{
count = ;
}
}
return ;
}

>>对接受到的截图数据流进行'\n'字符还原

                var count = Find0DCount(memoStream);

                var newStream = new MemoryStream();
memoStream.Position = ;
while (memoStream.Position != memoStream.Length)
{
var b = memoStream.ReadByte();
if (b == '\r')
{
int c = ;
var b1 = memoStream.ReadByte();
while(b1 == '\r' && memoStream.Position != memoStream.Length)
{
c++;
b1 = memoStream.ReadByte();
}
if(b1 == '\n')
{
if(c == count)
{
newStream.WriteByte((byte)'\r');
}
newStream.WriteByte((byte)b1);
}
else
{
for(int i=; i<c; i++) newStream.WriteByte((byte)'\r');
newStream.WriteByte((byte)b1);
}
}
else {
newStream.WriteByte((byte)b);
}
} return new Bitmap(newStream);

3、获取棋子与跳跃落脚点位置

将获取到的手机界面截图显示到软件窗体上的PictureBox控件上,可用鼠标的左右键分别点击图片位置标示棋子位置和需要跳的落脚点位置,鼠标点击的坐标位置即表示手机界面的坐标位置。由于手机界面截图在PictureBox控件显示时为了能一屏全图显示,对图片做了缩放处理,且图片缩放后如果图片的宽度小于PictureBox控件的宽度,PictureBox会将图片居中后显示。所以鼠标点击的坐标位置还需要进行坐标转换才可以映射为手机界面里的绝对坐标位置。

转换计算方法:先计算PictureBox控件的图片缩放值和图片显示的左边距,然后再对鼠标点击坐标进行缩放计算。代码如下:

        private Point CalPoint(Point p)
{
if (this.cbZoom.Checked && this.pictureBox1.Image != null)
{
var zoom = (double)this.pictureBox1.Height / this.pictureBox1.Image.Height;
var width = (int)(this.pictureBox1.Image.Width * zoom);
var left = this.pictureBox1.Width / - width / ;
return new Point((int)((p.X - left) / zoom), (int)(p.Y / zoom));
}
else
{
return p;
}
}

如全靠手动鼠标点击坐标位置来玩游戏,这和直接在手机里手动玩游戏是没有什么区别的,区别只在于能够跳跃精准些(跳跃力度能自动计算出,下面会讲),所以程序还要能够实现自动化,就是要能够自动找出棋子与跳跃落脚点的位置。

A、找棋子的坐标位置

棋子的位置非常的好找,对游戏界面里的棋子(图2黄色块)进行放大可以发现棋子底部有一块区域(图3白色块)的颜色值是固定的R(54)G(60)B(102)颜色,如下两图:

(图2)

(图3)

根据棋子的这一颜色特点在获取到手机界面截图时,对图片象素进行扫描,查找R(54)G(60)B(102)这一颜色,找到的坐标位置就是棋子的位置。为了能快速扫描图片,不采用效率较低下的GetPixel方法获取颜色值,而采用LockBits方法锁定图片数据到内存,再采用指针移动获取象素颜色,由于采用了指针,代码需要开启unsafe定义。且棋子正常情况下不会在最顶部和最底部出现,所以不需要对整张界面图片扫描,只扫描20%-63%区域的数据,并且从底部开始找起。

B、找跳跃的落脚点位置

写此助手只是无聊时的产出物,所以我只是简单实现。游戏中如果连续跳到了目标物的中间位置时,新目标物的中间部分会出现一个白色圈(如上图2的红色块),如果再跳中此位置,会进行加分。根据这一特点,程序找出那一白色圈圈的位置即可做为落脚点位置,白色圈的颜色值为R(254)G(254)B(254),如果没有此白色圈位置,则手动鼠标选择落脚点位置。实现此功能后,程序基本上也能实现90%左右的自动化跳跃了。

查找代码实现如下:

private static Point FindPointImpl(Bitmap bitmap, out Point comboPoint)
{
var standPColor = Color.FromArgb(, , );
var comboPColor = Color.FromArgb(, , ); Point standPoint = Point.Empty;
comboPoint = Point.Empty; int y1 = (int)(bitmap.Height * 0.2);
int y2 = (int)(bitmap.Height * 0.63); PixelFormat pf = PixelFormat.Format24bppRgb; BitmapData bitmapData = bitmap.LockBits(new Rectangle(, y1, bitmap.Width, y2), ImageLockMode.ReadOnly, pf);
try
{
unsafe
{
int w = ;
while (y2 > y1)
{
byte* p = (byte*)bitmapData.Scan0 + (y2 - y1 - ) * bitmapData.Stride;
w = bitmap.Width;
int endColorCount = ;
while (w > )
{
ICColor* pc = (ICColor*)(p + w * );
if (standPoint == Point.Empty &&
pc->R == standPColor.R && pc->G == standPColor.G && pc->B == standPColor.B)
{
standPoint = new Point(w - , y2);
if (comboPoint != Point.Empty) break;
}
else if (comboPoint == Point.Empty)
{
if (pc->R == comboPColor.R && pc->G == comboPColor.G && pc->B == comboPColor.B)
{
endColorCount++;
}
else
{
if (endColorCount > )
{
comboPoint = new Point(w + , y2 - );
if (standPoint != Point.Empty) break;
}
endColorCount = ;
}
}
w--;
}
if (comboPoint == Point.Empty)
{
if (endColorCount > )
{
comboPoint = new Point(w + , y2 - );
}
}
if (standPoint != Point.Empty && comboPoint != Point.Empty) break;
y2--;
}
}
return standPoint;
}
finally
{
bitmap.UnlockBits(bitmapData);
}
}

4、棋子跳跃

要能跳跃,首先需要知道一个蓄力时间,就是按住棋子多久的时间,此蓄力时间的计算公式如下:

蓄力时间 = 距离 * 力度系数

  

“距离”就是棋子位置与跳跃落脚点位置的距离,根据上面的方法得出这两个位置的坐标点后,根据直角三角形的勾股定理即可求出,代码如下:

        public double Distance
{
get
{
if (!this.CanDo) return -1;
int w = Math.Abs(this.P2.X - this.P1.X);
int h = Math.Abs(this.P2.Y - this.P1.Y);
return Math.Sqrt((double)(w * w) + (h * h));
}
}

“力度系数”  是一个常量值,具体怎么定义没去细查,我采用的计算公式是: “力度系数 = 1495 / 手机分辨率的宽度值”, 如我的手机分辨率是1080*1920,则力度系数就是 1495 / 1080 = 1.3842....

算出了蓄力时间后通过以下adb命令发送到手机即可模拟点击操作。

adb shell input swipe <x1> <y1> <x2> <y2> [duration(ms)]

x1, y1 就是棋子的坐标位置

x2, y2 还是棋子的坐标位置

duration 蓄力时间值,由距离*力度系数得出。

代码如下:

        public bool Do()
{
if (!this.CanDo) return false; var startInfo = new ProcessStartInfo("adb", string.Format("shell input swipe {0} {1} {0} {1} {2}", this.P1.X, this.P1.Y, this.Time));
startInfo.CreateNoWindow = true;
startInfo.ErrorDialog = true;
startInfo.UseShellExecute = false;
var process = Process.Start(startInfo);
return process.Start();
}

三、结束语

程序实现很简单,都是通过adb命令与手机进行交互操作。如果你认为对你有帮助麻烦赞下即可:)积分别玩太过哦。

可执行文件下载地址:JumperHelper.rar

代码仓库:https://github.com/kingthy/JumperHelper

声明:本软件、代码和文章属于本人原创,转载请通知并注明原处!

用C#实现微信“跳一跳”小游戏的自动跳跃助手的更多相关文章

  1. charles刷分微信跳一跳小程序对https的理解

    以前以为只要安装了https 客户端与服务端的数据会被加密就安全了 事实上 只要任意一款抓包工具 并伪造证书  就可以解密这个被所谓https加密的数据 如  可以下载charles的根证书  作为伪 ...

  2. 微信跳一跳,Python辅助自动跳程序

    一.说明 此代码借鉴一位大神提供在gitHub上的源码,已经做了简化合并处理,成功连上手机并运行后,可实现自动玩微信跳一跳游戏,刷个1000+的分数轻轻松松 github源码地址 https://gi ...

  3. 【辅助工具】Python实现微信跳一跳

    最近迷上了微信跳一跳小游戏,正好也看到知乎上有大神分享了技术贴,我也参考了好多资料,原理就是通过abd命令截取图片,python计算两个点距离,然后转化按压时间,让电脑来完成游戏.我花了很长时间才把程 ...

  4. 微信跳一跳辅助Demo

    [原创] 前几天没事干看别人一直在玩微信上线的那一个跳一跳小游戏,玩着玩着老是掉下去,闲着没事呗 就想了想做一个辅助程序的呗.不过先做的手动版的.自动版的有点麻烦.就不发了.用的Java写的,也就一个 ...

  5. PYTHON 实现的微信跳一跳【辅助工具】仅作学习

    备注原地址:https://my.oschina.net/anlve/blog/1604163 我又做了一些优化,防止WX检测作弊 准备环境: Windows 10安卓手机,源码中有适配ios,然后链 ...

  6. 用Python来玩微信跳一跳

    微信2017年12月28日发布了新版本,在小程序里面有一个跳一跳小游戏,试着点一点玩了下.第二天刚好在一篇技术公众号中,看到有大神用Python代码计算出按压时间,向手机发送android adb命令 ...

  7. 微信跳一跳Python

    微信最新的小程序里面出了个叫“跳一跳”的小游戏,大神们也通过Python实现了自动玩游戏具体代码 如下: Github地址: https://github.com/wangshub/wechat_ju ...

  8. 微信跳一跳辅助自动跳Python

    一.说明 此代码借鉴github一位大神所写,已经做了简化合并处理,如果能成功连上手机并运行,可以实现程序自动玩游戏,刷个1000+的分数轻轻松松 github源码地址 https://github. ...

  9. 教你用.Net来玩微信跳一跳

    目前开发的所有代码都已经上传到了GitHub.欢迎大家来Star https://github.com/GiantLiu/AutoJump 目前程序分为“全自动版本”和“半自动版本” 全自动版本 We ...

随机推荐

  1. QTP生成随机数字+字母

    以下函数实现随机生成17位数(包括字母和数字),仍有改进的空间,可根据具体要求适当修改 Dim targetstring '调用返回函数给变量.Function过程通过函数名返回一个值 targets ...

  2. php数据库备份脚本

    // 备份数据库 $host = "localhost"; $user = "root"; //数据库账号 $password = ""; ...

  3. 配置scrapy-splash+python爬取医院信息(利用了scrapy-splash)

    北京艾丽斯妇科医院(http://fuke.fuke120.com/) 首先先说一下配置splash 1.利用pip安装scrapy-splash库 pip install scrapy-splash ...

  4. tp中like多字段同时怎么模糊搜索

    例如 select * from tbl where a like '%123%' or b like '%123%' or c like '%123%' ;实现这样的功能,thinkphp怎么写呢? ...

  5. Hibernate学习(三)自动建表

    一般情况下有如下两种方法: 1.在配置文件中添加如下配置 <property name="hibernate.hbm2ddl.auto">create</prop ...

  6. java基础部分的简单应用

    牛刀小试,MMP:嘿嘿,如有转载,请声明地址http://www.cnblogs.com/jinmoon/: 图形类,点类,三角形类,汽车类,接口:运用继承,抽象类,接口,多态:已知点类三点,输出三点 ...

  7. 直播二:iOS中硬编码(VideoToolBox)

    硬编码相对于软编码来说,使用非CPU进行编码,如显卡GPU.专用的DSP.FPGA.ASIC芯片等,性能高,对CPU没有压力,但是对其他硬件要求较高(如GPU等). 在iOS8之后,苹果开放了接口,并 ...

  8. Excel大写和小写转换函数

    Excel中的大写和小写转换函数 (1).转换为所有小写字母:lower函数 (2).转换为所有大写字母:upper函数 (3).转换为首字母大写,其余小写字母:proper函数 三种函数的使用方式. ...

  9. Android之——ListView优化

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47209253 作为client.其最基本的任务就是最直观的和用户交互.从serve ...

  10. 多域名环境,页面获取url的一种方案

    因为系统是分布式部署的.而且有多个域名,所以常常涉及到获取url的问题. 这是系统框架层面须要提供的能力.否则每一个模块都须要自己去想办法获取ip,就会非常混乱.上线也easy发生bug 主要须要解决 ...