Rotate PShape with mouse/keyboard

edited November 2013 in How To...

Hello guys, I'm creating a simple game with a cannon. I would like to move the cannon using an axis point, but I haven't managed to do that. Here is my code:

//New Pshapes
PShape theBanner;
PShape theBackground;
PShape theCannonBall;
PShape theCannonBaseFront;
PShape theCannonBaseRear;
PShape theCannon;
PShape thePlatformTop;
PShape thePlatformBottom;

//New font
PFont Font1;

//Objects variables
float theBannerW=166;
float theBannerH=96;
float theBannerX=30;
float theBannerY=0;

float theCannonBallW=50;
float theCannonBallH=theCannonBallW;

float theCannonBaseFrontW=107;
float theCannonBaseFrontH=81;

float theCannonBaseRearW=221;
float theCannonBaseRearH=120;

float theCannonW=140;
float theCannonH=118;
float theCannonX=120;
float theCannonY=335;

float thePlatformTopW=232;
float thePlatformTopH=330;

float thePlatformBottomW=232;
float thePlatformBottomH=330;

int theScore = 0;

void setup() {
  size(640, 480);
  background(100, 0, 200);
  frameRate(30);
  smooth();

  //Text for the score
  Font1 = createFont("Arial Black", 22);
  fill(0);
  textAlign(CENTER);

  //Loading vector graphics
  theBanner = loadShape("img/banner001.svg");
  theBackground = loadShape("img/bg001.svg");
  theCannonBall = loadShape("img/cannon_ball001.svg");
  theCannonBaseFront = loadShape("img/cannon_base_front001.svg");
  theCannonBaseRear = loadShape("img/cannon_base_rear001.svg");
  theCannon = loadShape("img/cannon001.svg");
  thePlatformTop = loadShape("img/platform001.svg");
  thePlatformBottom = loadShape("img/platform002.svg");
}

void draw() {
  background(0, 200, 250);
  //Score
  textFont(Font1);
  text("Score: "+theScore, theBannerX+80, theBannerY+82);
  //Graphics
  shape(theBackground, 0, 0, width, height);
  shape(theBanner, theBannerX, theBannerY, theBannerW, theBannerH);
  shape(theCannonBaseRear, 16, 360, theCannonBaseRearW, theCannonBaseRearH);
  shapeMode(CENTER);
  shape(theCannon, theCannonX, theCannonY, theCannonW, theCannonH);
  shapeMode(CORNER);
  shape(theCannonBaseFront, 53, 365, theCannonBaseFrontW, theCannonBaseFrontH);
  shape(thePlatformTop, 345, -60, thePlatformTopW, thePlatformTopH);
  shape(thePlatformBottom, 345, 270, thePlatformBottomW, thePlatformBottomH);
  shape(theCannonBall, width/2, height/2, theCannonBallW, theCannonBallH);
}

To clear things out, here is the graphic to have a better idea of what I'm trying to achieve: Instructions-Game-1-03

Any ideas how to solve my issue?

Answers

  • I would like to specify the axis point. This solution rotates the cannon from the (0,0) position, that's not what I want:

    //KEY PRESSED
    void keyPressed() {
      if (keyCode==UP) {
        theCannon.rotate(-0.1);
      }
      if (keyCode==DOWN) {
        theCannon.rotate(0.1);
      }
    
  • edited November 2013

    This was useless too, unless I'm doing something wrong:

    //KEY PRESSED
    void keyPressed() {
      if (keyCode==UP) {
        pushMatrix();
          translate(68,70);
          theCannon.rotate(radians(-1));
        popMatrix();
      }
      if (keyCode==DOWN) {
        pushMatrix();
          translate(68,70);
          theCannon.rotate(radians(1));
        popMatrix();
      }
    }
    
  • edited November 2013

    I rewrite my code and now I'm using a class for the "cannon":

    //New Pshapes
    PShape theBanner;
    PShape theBackground;
    PShape theCannonBall;
    PShape theCannonBaseFront;
    PShape theCannonBaseRear;
    PShape theCannon;
    PShape thePlatformTop;
    PShape thePlatformBottom;
    
    //New font
    PFont Font1;
    
    //Objects variables
    float theBannerW=166;
    float theBannerH=96;
    float theBannerX=30;
    float theBannerY=0;
    
    float theCannonBallW=50;
    float theCannonBallH=theCannonBallW;
    
    float theCannonBaseFrontW=107;
    float theCannonBaseFrontH=81;
    
    float theCannonBaseRearW=221;
    float theCannonBaseRearH=120;
    
    float thePlatformTopW=232;
    float thePlatformTopH=330;
    
    float thePlatformBottomW=232;
    float thePlatformBottomH=330;
    
    int theScore = 0;
    
    //Declaring objects
    Cannon myCannon;
    
    void setup() {
      size(640, 480);
      background(100, 0, 200);
      frameRate(30);
      smooth();
    
      //Text for the score
      Font1 = createFont("Arial Black", 22);
      fill(0);
      textAlign(CENTER);
    
      //Loading vector graphics
      theBanner = loadShape("img/banner001.svg");
      theBackground = loadShape("img/bg001.svg");
      theCannonBall = loadShape("img/cannon_ball001.svg");
      theCannonBaseFront = loadShape("img/cannon_base_front001.svg");
      theCannonBaseRear = loadShape("img/cannon_base_rear001.svg");
      theCannon = loadShape("img/cannon001.svg");
      thePlatformTop = loadShape("img/platform001.svg");
      thePlatformBottom = loadShape("img/platform002.svg");
    
      //Asigning values to the objects
      myCannon = new Cannon(140, 118, 120, 335, 1);
    }
    
    void draw() {
      background(0, 200, 250);
      //Score
      textFont(Font1);
      text("Score: "+theScore, theBannerX+80, theBannerY+82);
      //Graphics
      shape(theBackground, 0, 0, width, height);
      shape(theBanner, theBannerX, theBannerY, theBannerW, theBannerH);
      shape(theCannonBaseRear, 16, 360, theCannonBaseRearW, theCannonBaseRearH);
      // Call methods for the Bonus object    
      myCannon.cannonDisplay();
      shape(theCannonBaseFront, 53, 365, theCannonBaseFrontW, theCannonBaseFrontH);
      shape(thePlatformTop, 345, -60, thePlatformTopW, thePlatformTopH);
      shape(thePlatformBottom, 345, 270, thePlatformBottomW, thePlatformBottomH);
      shape(theCannonBall, width/2, height/2, theCannonBallW, theCannonBallH);
    }
    
    //KEY PRESSED
    void keyPressed() {
      if (keyCode==UP) {
        myCannon.rotateUp();
      }
      if (keyCode==DOWN) {
        myCannon.rotateDown();
      }
    }
    
    //Creating the class "Cannon"
    class Cannon {
      float cannonPosX;
      float cannonPosY;
      float cannonW;
      float cannonH;
      float cannonAngle;
    
      //Constructor
      Cannon(float cannonTempW, float cannonTempH, float cannonTempXPos, float cannonTempYPos, float cannonTempAngle) {
        cannonW = cannonTempW; /*Width of cannon*/
        cannonH = cannonTempH; /*Height of cannon*/
        cannonPosX = cannonTempXPos; /*X position of cannon*/
        cannonPosY = cannonTempYPos; /*Y position of cannon*/
        cannonAngle = cannonTempAngle; /*Angle of rotation*/
      }
    
      //Functionality
      void cannonDisplay() {
        /*
        PShape theCannon;
         theCannon = loadShape("img/cannon001.svg");
         */
        rectMode(CENTER);
        rect(cannonPosX, cannonPosY, cannonW, cannonH);
      }
    
      //Methods for moving up and down
      void rotateUp() {
        pushMatrix();
        translate(0, 0);
        theCannon.rotate(radians(-cannonAngle));
        popMatrix();
        println("Up");
      }
      void rotateDown() {
        pushMatrix();
        cannonPosX+=1;
        println("Down");
      }
    }
    

    However, I haven't managed how to rotate the object yet!

  • I would use rotate() (local, limited by pushMatrix()) instead of theCannon.rotate(). No need to rotate the shape, better draw it rotated.

  • That sounds logic. So you're suggesting me draw the object inside both methods rotateUp and rotateDown, isn't it? Would you mind explaining it a little more?

  • edited November 2013

    I would just update the cannonAngle in these methods.

    Note that:

    • translate(0, 0); is a no-op, ie. it does nothing.
    • rotateDown() has a pushMatrix() but not a popMatrix(), so you will have an error after calling it many times.
    • You should have these pushMatrix(); translate(cannonPosX, cannonPosY); rotate(radians(cannonAngle)); shape(theCannon); popMatrix(); in cannonDisplay() instead.
  • Not working. I changed the script to this:

     //Functionality
      void cannonDisplay() {
        theCannon = loadShape("img/cannon001.svg");
        shapeMode(CENTER);
        shape(theCannon,cannonPosX, cannonPosY, cannonW, cannonH);
      }
    
      //Methods for moving up and down
      void rotateUp() {
        pushMatrix();
          translate(cannonPosX, cannonPosY);
          rotate(radians(-cannonAngle));
          shape(theCannon);
        popMatrix();
        println("Up");
      }
      void rotateDown() {
        println("Down");
      }
    }
    

    It doesn't rotate.

  • Answer ✓

    More like this:

      void cannonDisplay() {
        // theCannon = loadShape("img/cannon001.svg"); // Move this to constructor!
        shapeMode(CENTER);
        pushMatrix();
          translate(cannonPosX, cannonPosY);
          rotate(radians(-cannonAngle));
          shape(theCannon);
        popMatrix();
      }
    
      //Methods for moving up and down
      void rotateUp() {
        cannonAngle--;
        println("Up");
      }
      void rotateDown() {
        cannonAngle++;
        println("Down");
      }
    

    The display uses the parameters, the rotateXxx() functions change the angle.
    Untested...

  • Excellent, now it behaves as I want! Thanks a lot, I was struggling since Thursday to come up with a proper solution.

Sign In or Register to comment.