Processing与Arduino互动编程 10. 4 摇杆控制坦克移动错误纠正

14 篇文章 1 订阅
4 篇文章 0 订阅

原书内容运行后无法显示坦克,可能作者并没有实际运行其代码,原代码如下:

import processing.serial.*; 
Serial myPort;
public static final char HEADER = 'M'; //数据 帧 头( 起始 位) 
public static final short LF = 10; //数据 帧 尾( 结束 位) 
public static final short portIndex = 2; 
public static final short centerX= 527; //摇杆 静止 时 X 轴 的 中点 值( 由于 不同 摇杆 的 中点 值 不同, 建议 读者 自行 测试 出 静止 的 中点 值, 并修 改) 
public static final short centerY= 507; //摇杆 静止 时 Y 轴 的 中点 值 
int x= 300, y= 200; //坦克 起始 位置 
int speed= 3; // 坦克 移动 的 速度, 读者 可自 行 修改 
char Direction; // 方向 判断 
class Tank 
{ 
Tank() { } 
void DisplayTank( int px, int py, char direction) 
{ 
  background(204); 
  switch(direction) 
  { 
  case 'F': //前行 
  fill( 255, 255, 0);
  rect( px-10, py, 20, 40); 
  rect( px+30, py, 20, 40); 
  ellipse( px+ 20, py+ 20, 20, 25);
  rect( px+17, py-10, 6, 19);   
  break; 
  case 'B': // 后退 
  fill( 255, 255, 0);
  rect( px-10, py, 20, 40);
  rect( px+30, py, 20, 40); 
  ellipse( px+20, py+20, 20, 25); 
  rect( px+ 17, py+ 30, 6, 19); 
  break; 
case 'L': //往左 行驶 
fill( 255, 255, 0); 
rect( px, py-10, 40, 20);
rect( px, py+30, 40, 20); 
ellipse( px+20, py+ 20, 25, 20); 
rect( px-10, py+17, 19, 6); 
break; 
case 'R': //往右 行驶 
fill( 255, 255, 0); 
rect( px, py-10, 40, 20); 
rect( px, py+30, 40, 20); 
ellipse( px+20, py+20, 25, 20); 
rect( px+30, py+17, 19, 6);
break;
default: 
break; 
}
} 
void boundary( int px, int py)

{ 
  if (px< 10) x= 10; 
  if (py< 10) y= 10; 
if (px>( width- 50)) x= width- 50; 
if (py>( height- 50)) y= height- 50;
} 
char tankDirection( int px, int py) //判断 坦克 移动 的 方向 
{ if ((px<(centerX-30))&&(abs( px- centerX)> abs(py- centerY))) Direction='L'; //往左 移动 
if ((px>( centerX+ 30))&&( abs( px- centerX)> abs( py- centerY))) Direction='R'; //往右 移动
if ((py<( centerY- 30))&&( abs( px- centerX)< abs( py- centerY))) Direction='F'; //往前 移动 
if ((py>( centerY+ 30))&&( abs( px- centerX)< abs( py- centerY))) Direction='B'; //往后 移动 
if(( px>=( centerX- 30))&&( px<=( centerX+ 30))&&( py>=( centerY- 30))&&( py<= (centerY+ 30))) Direction='S'; //停止 
return Direction; //返回 方向 
} 
} 
Tank tank; 
void setup() 
{
 size( 640, 480);
tank= new Tank();
tank.DisplayTank(x,y,'F'); 
myPort= new Serial(this,"COM13",9600); 
myPort.clear(); 
}
void draw() {
}
void serialEvent(Serial myPort) 
{ 
  String message = myPort. readStringUntil( LF); //返回 一个 字符串 缓冲区, 并 包括 一个 特殊 字符 
  char direction; 
  if (message != null) 
  { 
    print( message); 
    String []data = message. split(","); //返回 带有 特殊 字符 的 字符串 
    println( data[1]); 
    println( data[2]); 
    if (data[0]. charAt(0) == HEADER) //读取 到 帧 头
    { 
      if (data.length > 2) 
      { 
        int tempX = Integer.parseInt(data[1]); //把 整型 对象 转换 成 基本 数据 类型 int 
        int tempY = Integer.parseInt(data[2]); 
        print("x = "+tempX ); 
        print(", y = "+tempY ); 
        direction= tank.tankDirection(tempX,tempY);
        //print(direction);

 switch(direction) 
 { 
 case 'F': 
 y= y- speed; 
 tank.boundary(x,y);
 tank.DisplayTank(x,y,'F');
 break; 
 case 'B':
 y= y+speed;
tank.boundary(x,y); 
 tank.DisplayTank(x,y,'B');
 break; 
 case 'L':
 x= x- speed; 
 tank.boundary(x,y); 
 tank.DisplayTank(x,y,'L');
 break; 
 case 'R': 
 x= x+speed;
 

 tank.boundary(x,y); 
 tank.DisplayTank(x,y,'R');

 break; 
 case 'S': 
 break;
 default: 
 break; 
 }
 }
 }
 }
 }

修改后的内容如下:

  1. 为了能够画出坦克,在draw()函数内加如下语句:
void draw() {

tank.DisplayTank(x,y,Direction);
}

2.为了能够使坦克在停止时不会消失,在串口函数中的 case’s’后加如下语句:

 case 'S': 
  tank.boundary(x,y); 
 tank.DisplayTank(x,y,'S');
 break;

3.为了能够使坦克在停止时不会消失,还要在Tank类定义内 case’s’后加如下语句:

case 'S': 
 fill( 255, 255, 0);
  rect( px-10, py, 20, 40); 
  rect( px+30, py, 20, 40); 
  ellipse( px+ 20, py+ 20, 20, 25);
  rect( px+17, py-10, 6, 19); 
default: 

这样修改后,坦克停止后不会消失,且炮管向上。
本打算使坦克停止后炮管与运动方向一致,学艺不精,没想到方法。
下面是改正后的完整代码

import processing.serial.*; 
Serial myPort;
public static final char HEADER = 'M'; //数据 帧 头( 起始 位) 
public static final short LF = 10; //数据 帧 尾( 结束 位) 
public static final short portIndex = 2; 
public static final short centerX= 527; //摇杆 静止 时 X 轴 的 中点 值( 由于 不同 摇杆 的 中点 值 不同, 建议 读者 自行 测试 出 静止 的 中点 值, 并修 改) 
public static final short centerY= 507; //摇杆 静止 时 Y 轴 的 中点 值 
int x= 300, y= 200; //坦克 起始 位置 
int speed= 3; // 坦克 移动 的 速度, 读者 可自 行 修改 
char Direction; // 方向 判断 
class Tank 
{ 
Tank() { } 
void DisplayTank( int px, int py, char direction) 
{ 
  background(204); 
  switch(direction) 
  { 
  case 'F': //前行 
  fill( 255, 255, 0);
  rect( px-10, py, 20, 40); 
  rect( px+30, py, 20, 40); 
  ellipse( px+ 20, py+ 20, 20, 25);
  rect( px+17, py-10, 6, 19);   
  break; 
  case 'B': // 后退 
  fill( 255, 255, 0);
  rect( px-10, py, 20, 40);
  rect( px+30, py, 20, 40); 
  ellipse( px+20, py+20, 20, 25); 
  rect( px+ 17, py+ 30, 6, 19); 
  break; 
case 'L': //往左 行驶 
fill( 255, 255, 0); 
rect( px, py-10, 40, 20);
rect( px, py+30, 40, 20); 
ellipse( px+20, py+ 20, 25, 20); 
rect( px-10, py+17, 19, 6); 
break; 
case 'R': //往右 行驶 
fill( 255, 255, 0); 
rect( px, py-10, 40, 20); 
rect( px, py+30, 40, 20); 
ellipse( px+20, py+20, 25, 20); 
rect( px+30, py+17, 19, 6);
break;
case 'S': 
 fill( 255, 255, 0);
  rect( px-10, py, 20, 40); 
  rect( px+30, py, 20, 40); 
  ellipse( px+ 20, py+ 20, 20, 25);
  rect( px+17, py-10, 6, 19); 
default: 
break; 
}
} 
void boundary( int px, int py)

{ 
  if (px< 10) x= 10; 
  if (py< 10) y= 10; 
if (px>( width- 50)) x= width- 50; 
if (py>( height- 50)) y= height- 50;
} 
char tankDirection( int px, int py) //判断 坦克 移动 的 方向 
{ if ((px<(centerX-30))&&(abs( px- centerX)> abs(py- centerY))) Direction='L'; //往左 移动 
if ((px>( centerX+ 30))&&( abs( px- centerX)> abs( py- centerY))) Direction='R'; //往右 移动
if ((py<( centerY- 30))&&( abs( px- centerX)< abs( py- centerY))) Direction='F'; //往前 移动 
if ((py>( centerY+ 30))&&( abs( px- centerX)< abs( py- centerY))) Direction='B'; //往后 移动 
if(( px>=( centerX- 30))&&( px<=( centerX+ 30))&&( py>=( centerY- 30))&&( py<= (centerY+ 30))) Direction='S'; //停止 
return Direction; //返回 方向 
} 
} 
Tank tank; 
void setup() 
{
 size( 640, 480);
tank= new Tank();
tank.DisplayTank(x,y,'F'); 
myPort= new Serial(this,"COM13",9600); 
myPort.clear(); 
}
void draw() {

tank.DisplayTank(x,y,Direction);
}
void serialEvent(Serial myPort) 
{ 
  String message = myPort. readStringUntil( LF); //返回 一个 字符串 缓冲区, 并 包括 一个 特殊 字符 
  char direction; 
  if (message != null) 
  { 
    print( message); 
    String []data = message. split(","); //返回 带有 特殊 字符 的 字符串 
    println( data[1]); 
    println( data[2]); 
    if (data[0]. charAt(0) == HEADER) //读取 到 帧 头
    { 
      if (data.length > 2) 
      { 
        int tempX = Integer.parseInt(data[1]); //把 整型 对象 转换 成 基本 数据 类型 int 
        int tempY = Integer.parseInt(data[2]); 
        print("x = "+tempX ); 
        print(", y = "+tempY ); 
        direction= tank.tankDirection(tempX,tempY);
        //print(direction);

 switch(direction) 
 { 
 case 'F': 
 y= y- speed; 
 tank.boundary(x,y);
 tank.DisplayTank(x,y,'F');
 break; 
 case 'B':
 y= y+speed;
tank.boundary(x,y); 
 tank.DisplayTank(x,y,'B');
 break; 
 case 'L':
 x= x- speed; 
 tank.boundary(x,y); 
 tank.DisplayTank(x,y,'L');
 break; 
 case 'R': 
 x= x+speed;
 

 tank.boundary(x,y); 
 tank.DisplayTank(x,y,'R');

 break; 
 case 'S': 
  tank.boundary(x,y); 
 tank.DisplayTank(x,y,'S');
 break;
 default: 
 break; 
 }
 }
 }
 }
 }

Arduino部分就不用修改了,按原书内容即可,代码如下:

int potXPin =A0;
int potYPin =A1;
char HEADER ='M';        

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int x =analogRead(potXPin);       //读取摇杆X轴数据
  int y =analogRead(potYPin);       //读取摇杆Y轴数据
  Serial.print(HEADER);             //输出数据帧头
  Serial.print(",");                //逗号分隔符
  Serial.print(x,DEC);              //X轴数据
  Serial.print(",");                //逗号分隔符
  Serial.print(y,DEC);              //Y轴数据
  Serial.print(",");                //逗号分隔符
  Serial.println();                 //输出换行符作为帧尾
  delay(50);
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值