【微信跳一跳物理辅助工具】来自美科微信公众号的实践-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 5445|回复: 1

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

[复制链接]
发表于 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侧
[mw_shl_code=cpp,true]/*
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();
}
[/mw_shl_code]

ARDUINO侧
舵机法
[mw_shl_code=cpp,true]/*

微信跳一跳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);    // 点击结束


}
*/


}
[/mw_shl_code]


光耦法:
[mw_shl_code=cpp,true]/*

微信跳一跳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);    // 点击结束


}

}
[/mw_shl_code]
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, 下载次数: 3)
发表于 2018-8-21 21:35 | 显示全部楼层
沧海的帖子介绍了processing摄像头的方法,值得学习,点个赞。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-12-1 01:04 , Processed in 0.080589 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表