查看: 1921|回复: 1

【微信跳一跳物理辅助工具】来自美科微信公众号的实践

[复制链接]
  • TA的每日心情
    开心
    2019-7-17 13:13
  • 签到天数: 264 天

    [LV.8]以坛为家I

    发表于 2018-8-19 23:28 | 显示全部楼层 |阅读模式
    本帖最后由 沧海笑1122 于 2018-8-19 23:34 编辑

    【玩具名称】微信跳一跳物理辅助工具---  来自美科微信公众号
    【基本玩法】在美科微信公众号上看到了一个很棒的应用,我做了一点改编,并且增加了光耦模拟触发的玩法,即:利用processing+摄像头进行微信跳一跳的画面捕捉,用鼠标点击计算出发点---目的地的距离。 将数据传送至arduino,利用ajson库解析,驱动舵机(或光耦)模拟手机触摸屏幕,实现“跳一跳”功能。我用了两种方法实现,一种是美科微信公众号分享的舵机法,另外一种是光耦法。 待我慢慢道来。
    很遗憾不能传输视频,因为微信跳一跳在优酷审核未通过。玩家可以看看图片吧。其实这是物理辅助工具,保留了80%以上的游戏乐趣。
    IMG_20180819_135624.jpg
    IMG_20180819_135631_a.jpg
    一、准备工作

    【硬件准备】
      
      
    内容
    数量
    备注
      
    1
      
    Arduino  UNO+扩展板(含舵机接口)
    1
    舵机单独供电,共gnd
      
    2
      
    摄像头
    1
    640×480
      
    3
      
    舵机(9g)
    1
    高精度金属舵机更佳
      
    4
      
    触摸臂
    1
    乐高玩具配件+导电泡沫(舵机玩法)
      
    5
      
    导线
    1
    作为触摸臂与人体接触的导体(舵机玩法)
      
    6
      
    手机
    1
    可以玩微信跳一跳的配置,与系统无关。
      
    7
      
    乐高玩具配件
    若干
    固定平板或者手机、固定舵机
      
    8
      
    PC817
    4
    光耦(用于光耦玩法)

    【软件准备】
      
      
    内容
    数量或者版本
    备注
      
    1
      
    processing
    V3.0+
    官网下载
      
    2
      
    Arduino  IDE
    V1.0
    经测试1.8.5不行,对ajson库支持不好
      
    3
      
    Ajson库
    V1.0
    Github.com
      
    4
      
    舵机库

    Ide自带
      
    5
      
    串口助手

    用于调试ajson库,运行时不需要

    看上去很简单对不对,实际上也不复杂。我们聊聊基本过程吧。


    二、电路连接
    示意图.jpg
    三、【代码】
    Processing侧

    kittenblock中小学创客名师推荐的图形化编程软件

    /*
    wx jump 
    from Microduino
    ajson+arduino
    2018-08-15
    
    */
    
    
    import processing.serial.*;
    import processing.video.*;
    import java.awt.*;
    
    Capture video;
    Serial myPort;
    
    int x0, x1, y0, y1, x2, y2;
    int distance;
    boolean runsta;
    String ajson_output;
    
    String dis = "";
    
    void setup() {
      size(640, 480);//场景窗口尺寸
      String portName = Serial.list()[1];
      println(Serial.list()[1]);//print COMx,核对你自己正在使用的com口
      myPort = new Serial(this, portName, 9600);
      video = new Capture(this, Capture.list()[18]);//根据输出的Capture.list(),你可以很快找到适合自己的分辨率,我选择的是640*480 30帧
      //video = new Capture(this, 640,480);
      printArray(Capture.list());
      video.start();
    }
    
    void draw() {
      scale(2);
      image(video, 0, 0 );
      if (mousePressed && (mouseButton == RIGHT)&&!runsta) { //右键点击开始
        x0=mouseX;
        y0=mouseY;
        println("x0:"+x0+", y0:"+ y0);
        runsta=true;
      } else if (mousePressed && (mouseButton == LEFT)&&!runsta) { //左键点击目的地
        x1=mouseX;
        y1=mouseY;
        x2=abs(x1-x0);
        y2=abs(y1-y0);
        distance=int(sqrt(x2*x2+y2*y2));
        println("x1:"+x1+", y1:"+ y1);
        println("distance:"+distance);
        dis=str(distance);
        //ajson_output
        //ratio 
            //生成json格式的延时系数以及距离,本例中是3.35,你可以根据自己实际跳跃情况进行标定,用二分法缩小(扩大),很快就可以找到。
        ajson_output="{\"jump\":{\"ratio\":"+str(3.35)+",\"dist\":"+dis+"}}"; //
        println("ajson_output:"+ajson_output);
        myPort.write(ajson_output);
        x0=x1;
        y0=y1;
        runsta=true;
      }
    }
    
    void mouseReleased() {
      runsta=false;
    }
    
    void captureEvent(Capture c) {
      c.read();
    }
    


    ARDUINO侧
    舵机法

    kittenblock中小学创客名师推荐的图形化编程软件

    /*
    
    微信跳一跳arduino端程序
    2018-08-18
    version:0.2
    基本原理:利用processing+摄像头+鼠标,测量跳跃点之间距离,将延时系数+跳跃距离用json格式+串口
    送至arduino,arduino+servo,经过延时后,实现跳跃功能。
    
    数据格式:
    {
            "jump":{
                    "ratio":4.65, 
                    "dist":110
            }
    }
    
    参考:
    1、ajosn库例题
    2、极客工坊技术贴 http://www.geek-workshop.com/thread-3407-1-1.html(作者quqianghao)
    */
    
    #include <aJSON.h>
    aJsonStream serial_stream(&Serial);
    #include <Servo.h>
    Servo myservo;
    #define servoPin  10   //servoPin is Pin D10
    #define ANGLEMIN 5
    #define ANGLEMAX 20
    //int pin_1=8;//数字口1
    //int pin_2=9;//数字口2
    float iratio=1.0;//延时系数
    int idist=1;//跳跃距离
    
    void setup() {
      Serial.begin(9600);
      //pinMode(pin_1, OUTPUT);//数字口1,因为腾讯对屏幕触碰有检测,不允许连续一个点触发
      //pinMode(pin_2, OUTPUT);//数字口2
      myservo.attach(servoPin);
      myservo.write(ANGLEMIN);
    }
    
    
    void loop()
    {
     
      if (serial_stream.available()) {
        /* First, skip any accidental whitespace like newlines. */
        serial_stream.skip();
      }
      if (serial_stream.available()) {
        /* Something real on input, let's take a look. */
        aJsonObject *msg = aJson.parse(&serial_stream);
        ComExecution(msg);  //解析数据并且实现相应动作
        aJson.deleteItem(msg);
      }
    }
    
    
    void ComExecution(aJsonObject *msg)//解析及动作函数
    {
      aJsonObject *jump = aJson.getObjectItem(msg, "jump");//跳跃参数
      if (jump) { //跳跃参数存在
          aJsonObject *j_ratio = aJson.getObjectItem(jump, "ratio"); //延时系数
          aJsonObject *j_dist = aJson.getObjectItem(jump, "dist");//跳跃距离
          iratio=j_ratio->valuefloat;;//延时系数为浮点型值
          idist=j_dist->valueint;//跳跃距离为整型值
          dojump();//调用跳跃函数,前提是存在跳跃系数
    }
    }
    
    void dojump()//跳跃函数
    {
     myservo.write(ANGLEMAX);//模拟点击屏幕
     delay(iratio*idist);         // 跳跃距离*延时系数
     myservo.write(ANGLEMIN); // 点击结束
      /*
    if (random(1, 10)<=5)//产生随机数,判断触摸点
    {
      // 模拟触摸1点
      digitalWrite(pin_1, HIGH);   // 模拟点击屏幕
      Serial.println(iratio);
      Serial.println(idist);
      delay(iratio*idist);         // 跳跃距离*延时系数
      digitalWrite(pin_1, LOW);    // 点击结束
    }
    else
    {
      // 模拟触摸2点
      digitalWrite(pin_2, HIGH);   // 模拟点击屏幕
      Serial.println(iratio);
      Serial.println(idist);
      delay(iratio*idist);         // 跳跃距离*延时系数
      digitalWrite(pin_2, LOW);    // 点击结束
    
    
    }
    */
    
    
    }
    



    光耦法:

    kittenblock中小学创客名师推荐的图形化编程软件

    /*
    
    微信跳一跳arduino端程序
    2018-08-15
    version:0.1
    基本原理:利用processing+摄像头+鼠标,测量跳跃点之间距离,将延时系数+跳跃距离用json格式+串口
    送至arduino,arduino生成一个随机数,分别驱动一个数字口输出,通过光耦实现模拟手指触动手机屏幕,经过延时后,实现跳跃功能。
    
    数据格式:
    {
            "jump":{
                    "ratio":4.65, 
                    "dist":110
            }
    }
    
    参考:
    1、ajosn库例题
    2、极客工坊技术贴 http://www.geek-workshop.com/thread-3407-1-1.html(作者quqianghao)
    */
    
    #include <aJSON.h>
    aJsonStream serial_stream(&Serial);
    
    int pin_1=8;//数字口1
    int pin_2=9;//数字口2
    float iratio=1.0;//延时系数
    int idist=1;//跳跃距离
    
    void setup() {
      Serial.begin(9600);
      pinMode(pin_1, OUTPUT);//数字口1,因为腾讯对屏幕触碰有检测,不允许连续一个点触发
      pinMode(pin_2, OUTPUT);//数字口2
    }
    
    
    void loop()
    {
     
      if (serial_stream.available()) {
        /* First, skip any accidental whitespace like newlines. */
        serial_stream.skip();
      }
      if (serial_stream.available()) {
        /* Something real on input, let's take a look. */
        aJsonObject *msg = aJson.parse(&serial_stream);
        ComExecution(msg);  //解析数据并且实现相应动作
        aJson.deleteItem(msg);
      }
    }
    
    
    void ComExecution(aJsonObject *msg)//解析及动作函数
    {
      aJsonObject *jump = aJson.getObjectItem(msg, "jump");//跳跃参数
      if (jump) { //跳跃参数存在
          aJsonObject *j_ratio = aJson.getObjectItem(jump, "ratio"); //延时系数
          aJsonObject *j_dist = aJson.getObjectItem(jump, "dist");//跳跃距离
          iratio=j_ratio->valuefloat;;//延时系数为浮点型值
          idist=j_dist->valueint;//跳跃距离为整型值
          dojump();//调用跳跃函数,前提是存在跳跃系数
    }
    }
    
    void dojump()//跳跃函数
    {
    if (random(1, 10)<=5)//产生随机数,判断触摸点
    {
      // 模拟触摸1点
      digitalWrite(pin_1, HIGH);   // 模拟点击屏幕
      Serial.println(iratio);
      Serial.println(idist);
      delay(iratio*idist);         // 跳跃距离*延时系数
      digitalWrite(pin_1, LOW);    // 点击结束
    }
    else
    {
      // 模拟触摸2点
      digitalWrite(pin_2, HIGH);   // 模拟点击屏幕
      Serial.println(iratio);
      Serial.println(idist);
      delay(iratio*idist);         // 跳跃距离*延时系数
      digitalWrite(pin_2, LOW);    // 点击结束
    
    
    }
    
    }
    

    IMG_20180819_173842_a.jpg IMG_20180819_173737_a.jpg
    【其他】
    1、关于光耦触摸的制作
    电容触摸屏的“被动式”操作,必须将触摸体与人体连接,光耦触摸其实就是这个原理,将一块湿巾剪成1cm*1cm,润湿后,贴在屏幕上,用金属线引出,连接在手指上。当D8/D9有高电平输出时,光耦导通,形成两个通路,使得屏幕与手指形成通路。注意:一是湿巾必须保持湿润,最好加点盐水。二是水不能溢出。因此比较难控制。
    为什么用两个数字口?微信已经对一个位置的触摸进行了限制,所以我们用一个随机数控制两个数字口(两个屏幕位置)的模拟点击。
    优点:精准;缺点:保持接触点的湿润是一件很头疼的事情。
    2、关于舵机触摸的制作
    舵机触摸比较简单可靠,用一块导电泡沫听起来是不是很高大上,其实就是美科产品包装盒里面的那块小小的防静电屏蔽泡沫,里面加入了碳,所以是导电泡沫,用于模拟手指触摸屏幕是再好不过了。把它切一小块绑在舵机臂上,加上导线连接至手指,就可以非常可靠地模拟手指触摸屏幕。
    优点:稳定、可靠,缺点:舵机(尤其是廉价舵机)精度不高,玩的时候不如光耦法成就感高,但是游戏的乐趣要更大。所以,推荐舵机法。
    导电泡沫.jpg
    3、微信对辅助工具的限制
    我们这个研究仅仅是极客的探索,不是让你冲排行榜的,况且我们想到的,腾讯早就想到了,所以对很多高分操作,微信都会提示你“刚才的分数存在可疑操作”,从而不纳入排行榜,我建议大家不要纠结这个。也不要去试图规避微信的审查。因为信息不对称,你的努力往往收效不大。而在这个项目中获得的乐趣,才是最有价值的。
    【感谢】
    1、感谢美科微信公众号,并且提供了完整的代码,我只是在延时系数的传送以及光耦玩法上做了一些修改,是站在美科高手的肩膀上的一次尝试。感谢该项目的原作者,如果我得到了名字,会及时更正致谢。
    2、感谢极客工坊技术贴http://www.geek-workshop.com/thread-3407-1-1.html(作者quqianghao)
    我的代码以及库,都打包附上,供各位玩家参考。
    沧海的2018年,经历了很多曲折煎熬,感谢支持我的人们,世事无常,唯有珍惜眼前,祝各位玩家诸事顺意。沧海合十。


    jump.zip (25.7 KB, 下载次数: 1)
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-8-24 21:42
  • 签到天数: 101 天

    [LV.6]常住居民II

    发表于 2018-8-21 21:35 | 显示全部楼层
    沧海的帖子介绍了processing摄像头的方法,值得学习,点个赞。
    打赏作者鼓励一下!
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    ArduinoJason6教程由ArduinoJson作者Benoit亲自出马一对一教学
    ArduinoJason6教程由Ardui
    这几天我觉得社区教学好像缺了点什么,呃呃~我想一想好像是缺少了ArduinoJson6的教学
    Arduino+L298N小车实例教程
    Arduino+L298N小车实例教
    (第一次写教程,如有错漏,敬请拍砖)Arduino+L298N小车实例教程Arduino小车是一个非
    零知开源分享-蓝牙模块与手机APP通信
    零知开源分享-蓝牙模块与
    本篇文章中将讲解蓝牙模块与安卓手机APP进行通信。1、说明MCU:零知开发板-标准板模
    DHT库无法被找到
    DHT库无法被找到
    今天在安装了DHT库之后在编译时却显示无法找到库,请问我是在哪里安装出错了,谢谢大
    (可远程)ESP8266读DHT11温湿度,APP inventor制作app实时显示
    (可远程)ESP8266读DHT11
    原理讲解 原理简述:利用发布订阅模式。第一步,先读取DHT11温湿度数值,第二步,新
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表