Tank movement seen from above

Hello,
Im new to processing and coding in general. Im trying to code a “tank” move around (seen from above). I want to have a tank rotate left when pressing keyboard “A” and right when pressing “D”. And I want it to drive forwards and backwards when pressing “W” and “S”.

I have a hard time finding any code from somebody else who have done the same thing. Its really annoying because it feels like it would be a really simple thing but I admit I really need some help. I have tried multiple things using vectors, trigonometry and 2D transformation.

I should also probably mention that my intention is to have a “tank-like” robot send its driving distance to processing via serial. And plot that information in that top view so that I can kind of see a navigation map of the robot.

I would really appriciate some help.

Here is the code that I have now. (Dont mind the created lines, its just so that I can see where the translate function is atm)

float x,y;
float angle;

void setup() { 
  size(600, 600);
  x = 0;
  y = 0;
  angle = 0;
  noFill();
  stroke(0);
  strokeWeight(1);
} 
 

void draw() {
  background(255);
  translate(width/2,height/2);
  line(0,0,0,-20);
  line(-10,0,10,0);
  
  //pushMatrix();

  
  //popMatrix();
  

  translate(x,y);
  
  rotate(radians(angle));
  line(0,0,0,-20);
  line(-10,0,10,0);
  
  translate(x,y);
  line(0,0,0,-20);
  line(-10,0,10,0);


  point(0,0);
  rectMode(CENTER);
  rect(0,0, 20, 40);

  update();

} 


void update() {
  if(keyPressed) {
    print(angle + "    ");
    println(key);
      if(key == 'w' || key =='W') {
          y = y - 1;
      }
      if(key == 'a' || key =='A') {
           angle = angle - 1;
      }
  }
}

A question that describes the problem? Posted code that is formatted properly? Shown effort?

Amazing! You win a solution:

float x, y;
float angle;

void setup() { 
  size(600, 600);
  x = width/2;
  y = height/2;
  angle = 0;
  noFill();
  stroke(0);
  strokeWeight(1);
  rectMode(CENTER);
} 


void draw() {
  background(255);
  update();
  translate(x,y);
  rotate(angle);
  line(0, 0, 0, -20);
  line(-10, 0, 10, 0);
  rect(0, 0, 20, 40);
} 


void update() {
  if (keyPressed) {
    if (key == 'w' || key =='W') {
      x+=4*cos(angle-HALF_PI);
      y+=4*sin(angle-HALF_PI);
    }
    if (key == 's' || key =='S') {
      x-=4*cos(angle-HALF_PI);
      y-=4*sin(angle-HALF_PI);
    }
    if (key == 'a' || key =='A') {
      angle = angle - radians(2);
    }
    if (key == 'd' || key =='D') {
      angle = angle + radians(2);
    }
  }
}

You could also create a Tank object if you are familiar with object-oriented programming :

class Tank{
  float x,y,angle;
  
  Tank(float xx,float yy,float a){
    x = xx;
    y = yy;
    angle = a;
  }
  
  void update(){
    if (key == 'w' || key =='W') {
      x+=4*cos(angle-HALF_PI);
      y+=4*sin(angle-HALF_PI);
    }
    if (key == 's' || key =='S') {
      x-=4*cos(angle-HALF_PI);
      y-=4*sin(angle-HALF_PI);
    }
    if (key == 'a' || key =='A') {
      angle = angle - radians(2);
    }
    if (key == 'd' || key =='D') {
      angle = angle + radians(2);
    }
  }
  
  void display(){
    translate(x,y);
    rotate(angle);
    line(0, 0, 0, -20);
    line(-10, 0, 10, 0);
    rect(0, 0, 20, 40);
  }
}

Thank you, that was perfect, I really needed the help. Now I understand quite a bit more as well. Thanks to both of you, I will take a further look at object-oriented programming in the near future.

Actually, do you think you can give me a brief description of what is happening in this piece of code?

    if (key == 'w' || key =='W') {
      x+=4*cos(angle-HALF_PI);
      y+=4*sin(angle-HALF_PI);
    }

I understand that it is the same as this, but I don’t understand quite what it does. For example where does the “4” come from? Thank you.

      x = x + 4*cos(angle-HALF_PI)
      y = y + 4*sin(angle-HALF_PI)

Ah ha, this is where it gets fun! Try out some variations of it to see what you get for example, try the following:

   x = x + 24*cos(angle-HALF_PI);
   y = y + 24*sin(angle-HALF_PI);

FAST TANK!

   x = x + 4*cos(angle);
   y = y + 4*sin(angle);

JANKY DIRECTION TANK!


If you have some trigonometry under your belt (and you should, if not, go get gud at learnin’ da maths), you’ll know that if you have a vector of length L that makes an angle of A with horizontal, then the vertical and horizontal components of that vector are L * cos(A) and L * sin(A), respectively. That should look familiar…

A drivable car. Not exactly a tank. But I guess it might help: :oncoming_automobile:
http://Studio.ProcessingTogether.com/sp/pad/export/ro.9Nl$898UQxW3Q

Aaah, now I see!

The “4” is just a speed multiplier. If you can believe it I actually do have trigonometry experience, but for me finding angles and length on paper is a whole other world than to implement it into code. Thank you again for your help, I really appreciate it.

Hold on a second, this is interesting. Processing is based on Java and Java is an object oriented language, but when I try to add your Tank and instantiate it, it says something about nested and cant hide an enclosing type? What is that problem?

Hold on another second, I found the solution. I “hacked” at it until it worked.

float x, y;
float angle;
tank Tank;
void setup() { 
  size(600, 600);
 //  Tank  = new tank();
  x = width/2;
  y = height/2;
  angle = 0;
  Tank  = new tank(x,y,angle);
  noFill();
  stroke(0);
  strokeWeight(1);
  rectMode(CENTER);
} 


void draw() {
  background(255);
 
  Tank.display();
   Tank.update();

}
class tank{
  float x,y,angle;
  
  tank(float xx,float yy,float a){
    x = xx;
    y = yy;
    angle = a;
  }
    void update(){
        if (keyPressed) {
    if (key == 'w' || key =='W') {
      x+=4*cos(angle-HALF_PI);
      y+=4*sin(angle-HALF_PI);
    }
    if (key == 's' || key =='S') {
      x-=4*cos(angle-HALF_PI);
      y-=4*sin(angle-HALF_PI);
    }
    if (key == 'a' || key =='A') {
      angle = angle - radians(2);
    }
    if (key == 'd' || key =='D') {
      angle = angle + radians(2);
    }
  }
 }
  
  void display(){
    translate(x,y);
    rotate(angle);
    line(0, 0, 0, -20);
    line(-10, 0, 10, 0);
    rect(0, 0, 20, 40);
  }
}

Without class

float x, y;
float angle;
boolean w, a, s, d;

void setup() { 
  size(600, 600);
  x = width/2;
  y = height/2;
  angle = 0;
  noFill();
  stroke(0);
  strokeWeight(1);
  rectMode(CENTER);
} 


void draw() {
  background(255);
  update();
  translate(x, y);
  rotate(angle);
  line(0, 0, 0, -20);
  line(-10, 0, 10, 0);
  rect(0, 0, 20, 40);
} 


void update() {
  if (w) {
    x+=4*cos(angle-HALF_PI);
    y+=4*sin(angle-HALF_PI);
  }
  if (s) {
    x-=4*cos(angle-HALF_PI);
    y-=4*sin(angle-HALF_PI);
  }
  if (a) {
    angle = angle - radians(2);
  }
  if (d) {
    angle = angle + radians(2);
  }
}

void keyPressed() {
  if (key == 'w' || key =='W') {
    w=true;
  }
  if (key == 's' || key =='S') {
    s=true;
  }
  if (key == 'a' || key =='A') {
    a=true;
  }
  if (key == 'd' || key =='D') {
    d=true;
  }
}

void keyReleased() {
  if (key == 'w' || key =='W') {
    w=false;
  }
  if (key == 's' || key =='S') {
    s=false;
  }
  if (key == 'a' || key =='A') {
    a=false;
  }
  if (key == 'd' || key =='D') {
    d=false;
  }
}

With class

Tank tank;

void setup() { 
  size(600, 600);
  tank = new Tank(width/2, height/2, 0);
  noFill();
  stroke(0);
  strokeWeight(1);
  rectMode(CENTER);
} 


void draw() {
  background(255);
  tank.update();
  tank.display();
} 

class Tank {
  float x, y, angle;
  boolean w, a, s, d;
  //
  Tank(int x, int y, int angle) {
    this.x=x;
    this.y=y;
    this.angle=angle;
  }
  //
  void update() {
    if (w) {
      x+=4*cos(angle-HALF_PI);
      y+=4*sin(angle-HALF_PI);
    }
    if (s) {
      x-=4*cos(angle-HALF_PI);
      y-=4*sin(angle-HALF_PI);
    }
    if (a) {
      angle = angle - radians(2);
    }
    if (d) {
      angle = angle + radians(2);
    }
  }
  //
  void display() {
    translate(x, y);
    rotate(angle);
    line(0, 0, 0, -20);
    line(-10, 0, 10, 0);
    rect(0, 0, 20, 40);
  }
}

void keyPressed() {
  if (key == 'w' || key =='W') {
    tank.w=true;
  }
  if (key == 's' || key =='S') {
    tank.s=true;
  }
  if (key == 'a' || key =='A') {
    tank.a=true;
  }
  if (key == 'd' || key =='D') {
    tank.d=true;
  }
}

void keyReleased() {
  if (key == 'w' || key =='W') {
    tank.w=false;
  }
  if (key == 's' || key =='S') {
    tank.s=false;
  }
  if (key == 'a' || key =='A') {
    tank.a=false;
  }
  if (key == 'd' || key =='D') {
    tank.d=false;
  }
}

1 Like

That is very interesting, I hacked at it and you applied concepts of object oriented programming. I know which is more powerful in the long run.