平方X 发表于 2017-12-30 19:42:18

[2460]程序猿是怎么玩游戏的——微信跳一跳各种思路总结



# 0x00 总结
## 0.1 学习
在整个过程中,自己列出了一些思路,最后选择了比较简单的实现。
另自己吃惊的是,一些自己能力不足无法实现的思路,都被别人很轻松的实现了。
自己还是要多学习。

## 0.2 效率
虽然自己也实现了,但已经不是第一个了,哇,好多 star 啊~ 错过了,哭。
不过,我是在乎 star 的人吗? 不是吗? 是吗? 不是吗?


一开始在网上搜了一下,没有找到相关的项目。
于是开始造轮子,等造好后,发现别人已经写好了,甚至和我的辣么像……
都是用 Python,都是用 adb 截图算距离,都是用 swipe 模拟点击,不知道的还以为我抄袭别人呢,哭晕在厕所,不开心……

[我的轮子](https://github.com/pingfangx/PythonX/tree/develop-toolsx/ToolsX/android/crack/wechat_game)
[别人的轮子](https://github.com/wangshub/wechat_jump_game)
整理一下自已想过的方案,

# 方案 01 修改内存
放弃

# 方案 02 抓包,改包,发包
最快速有效的方案,能力不足直接放弃,不过有大神实现了这一方案。
[麦文俊《微信跳一跳万分攻(作)略(弊)》](https://zhuanlan.zhihu.com/p/32473340)
> 其实我一开始抓包以为wxagame_battlereport是上传分数的,结果构造了数据包发现服务器并没有更新最高分……
后来抓包观察到破纪录以后发完settlement包紧接着的getFriendScore返回的个人信息已经是更新的。这个settlement包数据加密了,我只好去找小程序的源码。通过搜索引擎找到有关微信小程序包wxapkg的解包方法,找到了游戏的js文件。然后就在混淆的代码里面找到发请求的地方……

过程:
* 抓包
[小米用 fiddler 抓https](http://blog.pingfangx.com/2464.html)
* 改包
[微信跳一跳源码查看](http://blog.pingfangx.com/2463.html)
* 发包
(https://github.com/pingfangx/PythonX/blob/develop-toolsx/ToolsX/android/crack/wechat_game/wechat_game_post.py)

不过后来我测试的时候总是返回 -2 ,看了一下发包,已经包含了 game_data ,不知是否是这个原因,就没再处理。

# 方案 03 纯按键精灵找图,计算,模拟点击
找图不易实现,要整理所有可能出现的方块,不现实。
不过可以试一下找色。

# 方案 04 用 python 截图,计算,模拟点击
这是最终选择的方案,我将记录下我的方案过程,可以发现为什么最后造出的轮子和别人的那么像。

## 4.1 截图
### 4.1.1 adb
百度搜了一下,[叶桐《转-使用adb命令对手机进行截屏保存到电脑,SDCard》](http://blog.csdn.net/huangyabin001/article/details/29198367)
因为我文件夹比较多,我就转到 xx 了。
```
adb shell /system/bin/screencap -p /sdcard/xx/screenshot.png
adb pull /sdcard/xx/screenshot.png D:/xx/screenshot.png
```
此方法已被更新
```
https://github.com/wangshub/wechat_jump_game/blob/master/wechat_jump_auto.py
def pull_screenshot():
    global screenshot_way
    # 新的方法请根据效率及适用性由高到低排序
    if screenshot_way == 2 or screenshot_way == 1:
      process = subprocess.Popen('adb shell screencap -p', shell=True, stdout=subprocess.PIPE)
      screenshot = process.stdout.read()
      if screenshot_way == 2:
          binary_screenshot = screenshot.replace(b'\r\n', b'\n')
      else:
          binary_screenshot = screenshot.replace(b'\r\r\n', b'\n')
      f = open('autojump.png', 'wb')
      f.write(binary_screenshot)
      f.close()
    elif screenshot_way == 0:
      os.system('adb shell screencap -p /sdcard/autojump.png')
      os.system('adb pull /sdcard/autojump.png .')
```

### 4.1.2 投屏
只要把手机屏幕投到电脑上就可以方便计算了。
试了一下 (http://www.vysor.io/) ,结果没有安装上,就没再继续。

## 4.2 计算
首先我测出在初始状态下,dx=450,dy=260,需要按住 715ms ,正好可以跳到正中心。
又发现跳的距离与按住时间成正比,于是只需要测出要跳的距离即可。
### 4.2.1 手动测量
一开始想用 opencv ,但是试了一下没成功。为了快速刷个成绩,于是手动测量。
这个时候居然没有一个方便测量的工具,气得我想自己写一个,奈何我的 VS 居然打不开了,更气了几分。
这个时候使用的代码 (https://github.com/pingfangx/GameX/commit/e831da5a8aa013a03c2ce7c913461ed5df57f3a4)
[记 VS 与 python 的一次安装](http://blog.pingfangx.com/2465.html)

### 4.2.2 opencv
这应该是处理图片最好的方法,但是自己不太会用,最后只好放弃。
别人的实现 [船D长《用Python+Opencv让电脑帮你玩微信跳一跳》](https://zhuanlan.zhihu.com/p/32502071)
源码 (https://github.com/moneyDboat/wechat_jump_jump)
用的是模板匹配和边缘检测,我下面的思路是不是有点小白。


思路为,求轮廓,求轮廓中心
但是求轮廓需要将图转为黑白的,而小游戏中背景不是白的,反而有的方块却是白的。
于是想是否可以用颜色变换过滤掉背景,后来室友说后面的背景颜色可能会变,于是放弃。
(https://github.com/pingfangx/PythonX/commit/1c95c4d8adda0e2a973296620402c50390ed9e40)

(https://pypi.python.org/pypi/opencv-python)
(http://blog.csdn.net/sunny2038/article/details/12889059)
(http://python.jobbole.com/85600/)

### 4.2.3 python 写工具测量
一开始想用 C# 写一个,结果我的 VS 打不开了。
于是搜索 python 可不可以写一个测量工具。
[舍名利《Python3 Tkinter基础 Frame bind 绑定鼠标左右键 打印点击的位置 event.x event.x_root》](https://www.cnblogs.com/shemingli/p/6368655.html)
(http://blog.csdn.net/u011437680/article/details/40046719)
知道了可以用 Tkinter 实现(之前还绕了 pythoncom、pyautogui 等弯路)
于是用 Tkinter 实现了显示图片,按左键、右键量取距离,保存距离到文件。
(https://github.com/pingfangx/PythonX/commit/5a46382261e8b33c4571075e07bc80582ab864d1)

## 4.3 模拟点击
### 4.3.1 按键精灵 1
一开始我手动输入坐标,用按键精灵调用 Touch 模拟。
(https://github.com/pingfangx/GameX/blob/master/wechat_game/%E5%BE%AE%E4%BF%A1%E8%B7%B3%E8%B7%B3%E8%B7%B3(3b3a70b9-0c99-4396-9ab9-0ffdd3f320c9).mq)

### 4.3.2 按键精灵 2
后来觉得每次都要改太麻烦了,而 python 已经在 4.2.3 中实现了保存距离到文件。
于是修改为读取文件,执行 Touch
(https://github.com/pingfangx/GameX/blob/master/wechat_game/%E5%BE%AE%E4%BF%A1%E8%B7%B3%E8%B7%B3%E8%B7%B3(3b3a70b9-0c99-4396-9ab9-0ffdd3f320c9).mq)

### 4.3.3 python
那能不能不使用按键精灵,直接用 python 模拟点击呢?
搜了一下,找到 [小伍_《adb shell input的用法》](http://blog.csdn.net/longxiaowu/article/details/27336395)

```
在运行adb shell 后输入input后运行就会输出input的使用方法,如下:
Usage: input [<source>] <command> [<arg>...]


The sources are:
      trackball
      joystick
      touchnavigation
      mouse
      keyboard
      gamepad
      touchpad
      dpad
      stylus
      touchscreen


The commands and default sources are:
      text <string> (Default: touchscreen)
      keyevent [--longpress] <key code number or name> ... (Default: keyboard)
      tap <x> <y> (Default: touchscreen)
      swipe <x1> <y1> <x2> <y2> (Default: touchscreen)
      press (Default: trackball)
      roll <dx> <dy> (Default: trackball)
```
看到唯一一个可以设置时间的就是 swipe 了,但是但它是滑动,可以跳一跳吗,自己手滑了一下试试,没问题。

### 4.3.4 按下时间的计算
dx=450,dy=260,需要按住 715ms
这个时间用在 4.3.2 中,几乎都能跳到中心。
但换为 4.3.3 中的 swipe 之后,发现不正确了,第一次跳需要 765ms。
但换为 765ms,后面几次又跳不准了。几番测试后,修改为计算出的时间,再额外加上 50 ms
可能是因为 swipe 的原因,比按键精灵的 Touch 多消耗一段时间。

# 方案 05 手机端实现
虽然自己没有实现,但有别人实现了在手机端。
[黄艺彬《教你用JavaScript来玩微信跳一跳》](https://zhuanlan.zhihu.com/p/32499516)
源码 (https://github.com/hyb1996/WechatJumping.js)

我的思路:
在按下过程中,随时间增长画出一个圆圈。
该方案的问题是,如何确定跳的起点,又涉及到截图、找图了。
后来室友又给了一个思路,我觉得绝妙,可以改为从哪里跳就按住哪里嘛,用人去找起点。

还剩下一个问题是,如果拦截了触摸事件,会不会影响传到下地层的跳一跳去。

# 方案 06 自动化
这个最后都被大神们实现了。

主要卡在测量一步。
如果熟悉 opencv 应该是可以实现的。
先处理掉背景,然后求出轮廓。
轮廓大于一定面积认为是方块,求出方块中心。

也可以手写一个找图算法。
页: [1]
查看完整版本: [2460]程序猿是怎么玩游戏的——微信跳一跳各种思路总结