Python玩“跳一跳” iOS+Win 硬件实现

thehenry 6年前
   <p>感谢来自 <a href="/misc/goto?guid=4959756170398495771" title="wangshub">wangshub</a> 的跳跃距离算法</p>    <p>原项目地址:<a href="/misc/goto?guid=4959756170492298486" title="https://github.com/wangshub/wechat_jump_game">wangshub/wechat_jump_game</a></p>    <p>知乎专栏:<a href="/misc/goto?guid=4959756170584692644" rel="nofollow" title="教你用Python来玩微信跳一跳">教你用Python来玩微信跳一跳</a></p>    <p>本项目知乎专栏:<a href="/misc/goto?guid=4959756170672005153" rel="nofollow" title="python玩“跳一跳” iOS+Win版">python玩“跳一跳” iOS+Win版</a></p>    <p>目前已有的iOS跳一跳辅助需要macOS环境下的WebDriverAgentRunner。而现在介绍的方法在Windows环境下通过物理方法实现,不需要macOS也不需要越狱。</p>    <h2>运行环境&工具</h2>    <ul>     <li>Python 3.6 in Windows</li>     <li>Python Pillow库</li>     <li>局域网环境</li>     <li>iToools Airplayer</li>     <li>树莓派 或 arduino (本文使用树莓派)</li>     <li>SG90 舵机</li>     <li>杜邦线、纸板</li>     <li>一小块海绵</li>     <li>橙子或其它多汁水果(可选)</li>    </ul>    <h2>基本思路</h2>    <ol>     <li> <p>使用iOS自带Airplay服务将游戏画面投影到电脑上</p> </li>     <li> <p>使用Pillow库截取电脑屏幕,获得游戏画面</p> </li>     <li> <p>分析图片,计算出跳跃距离,乘以时间系数获得按压时间</p> </li>     <li> <p>将按压时间发送至树莓派,树莓派控制舵机点击手机屏幕</p> </li>    </ol>    <h2>原理 & 步骤</h2>    <h3>舵机 & 控制器 部分</h3>    <p>1.树莓派(OS:Raspbian Jessie)连接上局域网,下载 servo_control.py到树莓派;</p>    <p>2.拿一根杜邦线粘在舵机的摆臂上,并且固定好舵机。如图:</p>    <p><a href="https://simg.open-open.com/show/a406ecdb5f4ec4f1274f293251786e47.jpg"><img alt="" src="https://simg.open-open.com/show/a406ecdb5f4ec4f1274f293251786e47.jpg"></a></p>    <p>3.取一小块海绵,约10mm*10mm*5mm,不必太精确。海绵中间挖一个小洞。大概是这样: <a href="https://simg.open-open.com/show/828a437831967b1507ca54a677f86848.png"><img alt="" src="https://simg.open-open.com/show/828a437831967b1507ca54a677f86848.png"></a></p>    <p>4.海绵上滴水浸透,放在手机屏幕上“再来一次”的位置。杜邦线的另一头插进橙子(触发电容屏需要在屏幕上形成一个电场,我尝试过连接干电池负极的方案,但是效果不理想,最后不得已拿了室友的一个橙子。当然一直捏着或者含着导线也是可以的)。</p>    <p>5.舵机连接上树莓派,电源使用5v,舵机控制线接在GPIO18, 如图</p>    <p>6.需要根据实际安装位置调整舵机高点和低点位置<code>servo_down = 3.8 servo_up = 5</code>(范围: 2.5~12.5)</p>    <p>7.最终效果</p>    <p> <a href="https://simg.open-open.com/show/24cab030f26c04b9d3e38bb54392fb96.png"><img alt="" src="https://simg.open-open.com/show/a15ebe10a0e756aef371fe4d45a00c1c.jpg"></a></p>    <h3>Windows 部分</h3>    <ol>     <li> <p>下载<a href="/misc/goto?guid=4959756170796675225" rel="nofollow" title="Airplayer">Airplayer</a>(免安装,暂无捆绑)</p> </li>     <li> <p>配置Airplayer,画质什么的统统调到最高。启动iPhone上的Airplay,然后可以在电脑上到iPhone画面,游戏运行时需要Airplayer全屏显示。</p> </li>     <li> <p>安装Pillow库 本文使用Pillow库的ImageGrab截屏</p> <p><code>im = ImageGrab.grab((654, 0, 1264, 1080)) im.save('a.png', 'png')</code></p> <p>其中<code>(654, 0, 1264, 1080)</code>是截屏的范围,我的显示器分辨率是1080p,截取屏幕中间的部分得到的图片大小是610*1080,但这个时候图片最左边的一列的像素是黑色的。</p> </li>    </ol>    <p>4.下载<code>wechat_jump_auto_iOS_Win.py</code>,我的显示器分辨率是1920*1080,手机是iPhone 7。如果使用不同的设备需要更改时间系数等参数。</p>    <p>5.由于Airplay传输画面时会压缩,获取的游戏画面会有颜色偏差。我修改了原算法的一些参数,增大了一些颜色上的宽容度,在我的测试中达到一个比较好的准确率。</p>    <h2>运行</h2>    <ol>     <li> <p>打开游戏画面,Airplayer窗口全屏</p> </li>     <li> <p>树莓派上运行<code>servo_control.py</code></p> </li>     <li> <p>Windows运行<code>wechat_jump_auto_iOS_Win.py</code></p> </li>    </ol>    <h2>存在问题</h2>    <ul>     <li> <p>由于是物理点击屏幕,会产生一定的操作误差。操作误差由时间常数误差、舵机运动时间、杜邦线触点插进海绵的深度等等因素引起。而当前使用的算法在一种情况下会出现误差叠加的问题。</p> </li>     <li> <p>舵机的摆动角度和时间系数没有绝对的数值,需要慢慢尝试,当前使用的时间系数是2.43。</p> </li>    </ul>    <p> </p>