rotating an object and making it move with a variable

edited December 2016 in How To...

Hello, im remaking the atari game Asteroids as a beginner coder and im struggling on the rotation bit of the ship. im very new to rotate() and im not to sure how to make my ship rotate left and right. i also want to make the ship move in the direction its pointing using a variable so i can make sure the ship never leaves the screen size. i've tried to use translate() but i've come to relise that i dont know how to track a translation. can i please get some help, thanks.

Answers

  • void setup(){
      size(600,600);
    }
    
    void draw(){
      background(0);
    }
    

    This is an empty sketch. Clearly this works.

  • void setup(){
      size(600,600);
    }
    
    void draw(){
      background(0);
      rect(20,20,20,20);
    }
    

    Now there is a rectangle in it. Still works.

  • float x;
    float y;
    
    void setup(){
      size(600,600);
      x = 20;
      y = 20;
    }
    
    void draw(){
      background(0);
      rect(x,y,20,20);
    }
    

    Same rectangle, but now its position is controlled by the variables x and y.

  • Can we rotate it?

    float x;
    float y;
    
    void setup(){
      size(600,600);
      x = 20;
      y = 20;
    }
    
    void draw(){
      background(0);
      rotate(radians(20));
      rect(x,y,20,20);
    }
    

    Hm. That's not right. The rectangle has MOVED. We didn't want it to move away from (20,20) - we wanted it to rotate.

    But wait, to rotate, it needs a POINT to rotate around! What point is it rotating around?

  • Let's make it rotate a different amount every frame, so we can see which point it is rotating about.

    float x;
    float y;
    
    void setup(){
      size(600,600);
      x = 20;
      y = 20;
    }
    
    void draw(){
      background(0);
      rotate(radians(frameCount));
      rect(x,y,20,20);
    }
    

    Ah ha! It is rotating about the top left corner, (0,0)!

  • edited December 2016

    What if we MOVE SPACE? That is, what if we relocate our coordinate system so that (0,0) is at a different place?

    float x;
    float y;
    
    void setup(){
      size(600,600);
      x = 20;
      y = 20;
    }
    
    void draw(){
      background(0);
      translate(100,100);
      rotate(radians(frameCount));
      rect(x,y,20,20);
    }
    

    Ah, so that's what translate() does!

  • edited December 2016

    Okay. So. Let's move (0,0) so that it is where our rect should be. Then when we rotate, it will rotate about the point where it is. Of course, since we moved the coordinates of where (0,0) is to where we want the rect to be, we now need to draw the rect at (0,0).

    float x;
    float y;
    
    void setup(){
      size(600,600);
      x = 20;
      y = 20;
    }
    
    void draw(){
      background(0);
      translate(x,y);
      rotate(radians(frameCount));
      rect(0,0,20,20);
    }
    

    Hm. Closer. We're rotating about what looks like (20,20) now, but that is the corner of the shape, not the center.

  • Let's draw the rect so that it's center is now over the point where we're rotating.

    float x;
    float y;
    
    void setup(){
      size(600,600);
      x = 20;
      y = 20;
    }
    
    void draw(){
      background(0);
      translate(x,y);
      rotate(radians(frameCount));
      rect(-10,-10,20,20);
    }
    
  • Does this do what we want?

    float x;
    float y;
    
    void setup(){
      size(600,600);
      x = 20;
      y = 20;
    }
    
    void draw(){
      x = mouseX;
      y = mouseY;
      background(0);
      translate(x,y);
      rotate(radians(frameCount));
      rect(-10,-10,20,20);
    }
    

    Yes! The rect now rotates about it's center, no matter where it is located.

  • Of course, we wanted a spaceship.

    float x;
    float y;
    
    void setup(){
      size(600,600);
      x = 20;
      y = 20;
    }
    
    void draw(){
      x = mouseX;
      y = mouseY;
      background(0);
      translate(x,y);
      rotate(radians(frameCount));
      stroke(255);
      noFill();
      line(0,-10,10,10);
      line(10,10,0,5);
      line(0,5,-10,10);
      line(-10,10,0,-10);
    }
    
  • edited December 2016
    float ship_x;
    float ship_y;
    float ship_a;
    
    void setup() {
      size(600, 600);
      ship_x = width/2;
      ship_y = height/2;
      ship_a = 0;
    }
    
    void draw() {
      ship_simulate();
      ship_render();
    }
    
    void ship_simulate() {
      if (keyPressed && key == CODED) {
        if (keyCode == LEFT) ship_a--;
        if (keyCode == RIGHT) ship_a++;
        if (keyCode == UP) ship_y--;
        if (keyCode == DOWN) ship_y++;
      }
    }
    
    void ship_render() {
      background(0);
      translate(ship_x, ship_y);
      rotate(radians(ship_a));
      stroke(255);
      noFill();
      line(0, -10, 10, 10);
      line(10, 10, 0, 5);
      line(0, 5, -10, 10);
      line(-10, 10, 0, -10);
    }
    

    So let's use proper variable names, some useful functions, and throw in some keyPressed logic to move the ship...

  • What? The ship doesn't move right?

    Oh yeah, the direction it moves needs to change based on the angle it is rotated.

    float ship_x;
    float ship_y;
    float ship_a;
    
    void setup() {
      size(600, 600);
      ship_x = width/2;
      ship_y = height/2;
      ship_a = 0;
    }
    
    void draw() {
      ship_simulate();
      ship_render();
    }
    
    void ship_simulate() {
      if (keyPressed && key == CODED) {
        if (keyCode == LEFT) ship_a--;
        if (keyCode == RIGHT) ship_a++;
        if (keyCode == UP){
          ship_x += cos(radians(ship_a));
          ship_y += sin(radians(ship_a));
        }
      }
    }
    
    void ship_render() {
      background(0);
      translate(ship_x, ship_y);
      rotate(radians(ship_a));
      stroke(255);
      noFill();
      line(0, -10, 10, 10);
      line(10, 10, 0, 5);
      line(0, 5, -10, 10);
      line(-10, 10, 0, -10);
    }
    

    Clearly this works.

    Wait, what? it doesn't?

  • float ship_x;
    float ship_y;
    float ship_a;
    
    void setup() {
      size(600, 600);
      ship_x = width/2;
      ship_y = height/2;
      ship_a = -90;
    }
    
    void draw() {
      ship_simulate();
      ship_render();
    }
    
    void ship_simulate() {
      if (keyPressed && key == CODED) {
        if (keyCode == LEFT) ship_a--;
        if (keyCode == RIGHT) ship_a++;
        if (keyCode == UP){
          ship_x += cos(radians(ship_a));
          ship_y += sin(radians(ship_a));
        }
      }
    }
    
    void ship_render() {
      background(0);
      translate(ship_x, ship_y);
      rotate(radians(ship_a+90));
      stroke(255);
      noFill();
      line(0, -10, 10, 10);
      line(10, 10, 0, 5);
      line(0, 5, -10, 10);
      line(-10, 10, 0, -10);
    }
    

    Sneaky! The ship now starts off rotated a quarter turn to the left, but it's drawn a quarter turn to the right!

  • edited December 2016

    Give yourself a gold star if you saw this next step coming.

    class Ship {
      float x, y, a;
      Ship() {
        x = width/2;
        y = height/2;
        a = -90;
      }
      void draw() {
        simulate();
        render();
      }
      void simulate() {
        if (keyPressed && key == CODED) {
          if (keyCode == LEFT) a--;
          if (keyCode == RIGHT) a++;
          if (keyCode == UP) {
            x += cos(radians(a));
            y += sin(radians(a));
          }
        }
      }
      void render() {
        pushMatrix();
        translate(x, y);
        rotate(radians(a+90));
        stroke(255);
        noFill();
        line(0, -10, 10, 10);
        line(10, 10, 0, 5);
        line(0, 5, -10, 10);
        line(-10, 10, 0, -10);
        popMatrix();
      }
    }
    
    ///// -----
    
    Ship ship_zero;
    
    void setup() {
      size(600, 600);
      ship_zero = new Ship();
    }
    
    void draw() {
      background(0);
      ship_zero.draw();
    }
    
  • Gotta figure this as an assignment given that it's about the twentieth time it has been asked.

    Maybe someone oughta start teaching tfguy's code (again?)

  • Hello @TfGuy44

    What if I also wanted to move left or right without rotating...

  • Then you will need to change (or add to, if you also want to keep the rotating) the logic that deals with the key presses.

    Remember: x and y (in the Ship class, now) are the position of the ship. It is a simple matter to assign (use the assignment operator) those variables new values if certain conditions (use conditional statements) are met.

  • @TfGuy44 thanks a lot this should definitly help a ton I knw youve done so much, ive asked around and people tell me i should use a class instead of a PShape. I only use PShape becaue i semi inderstand it. If you could explain the difference in

  • edited December 2016

    A PShape is a type of common object that represents a Processing Shape (hence the name).

    You can read more about it here: https://processing.org/reference/PShape.html

    Or for an even more detailed look, here: http://processing.github.io/processing-javadocs/core/index.html?processing/core/PShape.html

    Heck, the source code for the PShape object is even online, here (I think?): https://github.com/processing/processing/blob/master/core/src/processing/core/PShape.java

    The point is this, however: A PShape is a common kind of object that you can use. You already use other (even more) common types of objects without thinking about it. Take, for example, int. Or float. Or String. Or maybe PImage. All of these objects are defined somewhere.

    This ability - being able to define a new type of object - is one that you also have! You define a new type of object when you write a class for it. The class is like a blueprint that details what fields and methods an instance of that class will have.

    The best example of this is one that I have already given - the Ship class, above.

    Notice that the Ship class contains some fields (x, y, and a) that it uses to remember things that are useful for the ship to know about itself. It also has some methods (draw(), simulate(), and render()) that you can call that do things on a given ship.

    If you really are writing an asteroids game, you will probably need two more classes. The first is a Bullet class, which you will use to track a shot fired by a Ship. The other is an Asteroid class, which tracks an asteroid.

  • edited December 2016

    common types of objects without thinking about it. Take, for example, int. Or float.

    Neither int nor float are objects in Java! They are directly accessed w/o any memory indirects. \m/

    There are 8 primitive datatypes in Java. And they're also keywords: :D
    http://docs.Oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

  • @TfGuy44 this worked out for me, i went a head and made a class for the asteroids and i tried to put it as asteroid.draw(); in my void draw(); just like you did for ship_zero.draw();. the thing is that it cant run both ship_zero.draw(); and asteroid.draw(); at the same time. do you know how to make it so it can?

  • edited December 2016

    Post your current code if you need more help. Be sure to format it correctly for these forums (Select code and press Ctrl + o).

  • edited December 2016

    @TfGuy44 sorry i couldn't get to you yesterday, heres my code:

        Ship drawShip;
        bigAsteroid drawBigAsteroid;
    
        void setup() {
          size(600,600);
          drawShip = new Ship();
          drawBigAsteroid = new bigAsteroid();
        }
    
        void draw() {
          background(0);
          drawShip.draw(); 
          drawBigAsteroid.draw();
        }
    

    i had made a class for the asteroid and i plan on making 2 more classes for the smaller asteroids. like i said when i run this you can only see the asteroid and i even switched the asteriod and the ship's .draw and it only showed the ship. my understanding is that it runs one and then throws it away and then runs the next. i want them to both run and i want it to run when i add the other classes, thanks!

  • edited December 2016

    Without seeing your bigAsteroid and Ship classes, we have no idea what your code is doing. Post the ENTIRE sketch.

  • edited December 2016
    ```class Ship {
    float xShip;
    float yShip;
    float aShip;
    
    Ship() {
      xShip = width/2;
      yShip = height/2;
      aShip = -90;
    }
    
    void draw() {
      drawShip();
      moveShip();
    }
    
    void drawShip() {
      pushMatrix();
      background(0);
      translate(xShip,yShip);
      rotate(radians(aShip+90));
      stroke(255);
      noFill();
      line(0,-10,10,10);
      line(10,10,0,5);
      line(0,5,-10,10);
      line(-10,10,0,-10);
      popMatrix();
     }
    
    void moveShip() {
      if (keyPressed && key==CODED) {
       if (keyCode==LEFT) aShip--;
       if (keyCode==RIGHT) aShip++;
       if (keyCode==UP) {
       xShip += cos(radians(aShip));
       yShip += sin(radians(aShip));
       }
      }
      if (xShip > 600) xShip = 0;
      if (xShip < 0) xShip = 600;
      if (yShip > 600) yShip = 0;
      if (yShip < 0) yShip = 600;
     }
    }
    class bigAsteroid {
      float xAsteroid;
      float yAsteroid;
      float xdeltaAst;
      float ydeltaAst;
    
      bigAsteroid() {
        xAsteroid = random(0,600);
        yAsteroid = random(0,600);
        xdeltaAst = random(-2,2);
        ydeltaAst = random(-2,2);
      }
    
      void draw() {
        drawAsteroid();
        moveAsteroid();
      }
    
      void drawAsteroid() {
        pushMatrix();
        background(0);
        translate(xAsteroid,yAsteroid);
        rotate(radians(frameCount));
        stroke(255);
        noFill();
        line(34,-60,60,0);
        line(60,0,34,60);
        line(34,60,-34,60);
        line(-34,60,-60,0);
        line(-60,0,-34,-60);
        line(-34,-60,34,-60);
        popMatrix();
      }
    
      void moveAsteroid() {
      xAsteroid = xAsteroid + xdeltaAst;
      yAsteroid = yAsteroid + ydeltaAst;
      if (xAsteroid > 600) xAsteroid = 0;
      if (xAsteroid < 0) xAsteroid = 600;
      if (yAsteroid > 600) yAsteroid = 0;
      if (yAsteroid < 0) yAsteroid = 600;
      }
     }
    
    Ship drawShip;
    bigAsteroid drawBigAsteroid;
    
    void setup() {
      size(600,600);
      drawShip = new Ship();
      drawBigAsteroid = new bigAsteroid();
    }
    
    void draw() {
      background(0);
      drawShip.draw(); 
      drawBigAsteroid.draw();
    }`
    
  • You have too many calls to background()!

  • edited December 2016

    There shouldn't be any calls to background inside other classes. All of them should come in the main class, and preferably only one in the start of draw(). Delete line 19 and 66.

This discussion has been closed.