简体   繁体   中英

How do I rotate and oscillate the same object in Processing

I am creating a snowflake simulation in Processing however i am not sure how to perform more than one transformation to an image as it seems you can only perform one.

class Snowflake{
  float imgWidth;
  float imgHeight;
  PVector pos;
  PVector vel;
  final float firstXPos;

  float a = 0.0;
  float angularVel = 0.01;

  float x;
  float amp;
  float period;

  Snowflake(float xWidth, float yHeight){
    imgWidth = xWidth;
    imgHeight = yHeight;
    pos = new PVector(random(width), 0);
    vel = new PVector(0,1);
    firstXPos = this.pos.x;
  }
  void descend(){
    amp = 75;  
    period = 200;

    x = amp * sin((frameCount/period) * TWO_PI);

This is where i am trying to rotate the image and oscillate it back and forth.

    pushMatrix();
    translate(firstXPos,this.pos.y);
    image(snowflakeImg, x, this.pos.y, imgWidth, imgHeight);
    popMatrix();

    //creating a line for oscillation reference
    //translate(firstXPos, this.pos.y);
    //stroke(255);
    //line(0,0,x,y);

}
  void update(){
    pos.add(vel);
    a += angularVel;
  }

}

Here is my sketch, just loading in assets and setting up the sketch

PImage snowflakeImg;
Snowflake snowFlake;

void setup() {
  imageMode(CENTER);
  snowflakeImg = loadImage("snowflake.png", "png");
  snowFlake = new Snowflake(25, 25);
  size(800,600);
}

void draw(){
  background(0);
  snowFlake.descend();
  snowFlake.update();  
}

You're creating a single Snowflake instance. You need to create more, then update each one.

In your case you should initialise an array of Snowflake objects first (at the top where you declare your variables). Here's an example allocating an array of 99 Snowflake objects:

int numSnowflakes = 99;
Snowflake[] snowflakes = new Snowflake[numSnowflakes]; 

Then in setup() you can initialise each array element as a new Snowflake instance:

for(int i = 0 ; i < numSnowflakes; i++){
    snowflakes[i] = new Snowflake(25, 25);
  }

Finally in draw() you can loop through each object so it can descend() and update() :

for(int i = 0 ; i < numSnowflakes; i++){
    snowflakes[i].descend();
    snowflakes[i].update();  
  }

If you're not familiar with arrays in Processing yet I can recommend the following resources:

  1. Processing arrays tutorial
  2. Processing ArrayObjects example
  3. Daniel Shiffman's Array of Objects Coding Train video tutorial along with Arrays and Loops

Once you've got the hang of this you should look into ArrayList as well.

Update To address your comment, you can use push/pop matrix calls to further isolate coordinate systems and rotate the image around it's centre:

x = amp * sin((frameCount/period) * TWO_PI);
// enter local coordinate system #1
pushMatrix();
// move to flake position
translate(firstXPos,this.pos.y);
  // enter local coordinate system #2
  pushMatrix();
    // move to updated (oscillated) x position
    translate(x, this.pos.y);
    // rotated from translated position (imageMode(CENTER) helps rotate around centre)
    rotate(frameCount * 0.1);
    // render the image at it's final transformation
    image(snowflakeImg,0,0, imgWidth, imgHeight);
  popMatrix();
popMatrix();

For more info check out the Coordinate Systems Processing tutorial .

For reference here's a test sketch I've used with each flake at random width:

PImage snowflakeImg;
Snowflake snowFlake;

int numSnowflakes = 99;
Snowflake[] snowflakes = new Snowflake[numSnowflakes]; 

void setup() {
  imageMode(CENTER);
  //snowflakeImg = loadImage("snowflake.png", "png");
  PGraphics snowflakeG = createGraphics(25,25);
  snowflakeG.beginDraw();
  snowflakeG.rectMode(CENTER);
  snowflakeG.rect(0,0,25,25);
  snowflakeG.endDraw();
  snowflakeImg = snowflakeG;

  for(int i = 0 ; i < numSnowflakes; i++){
    snowflakes[i] = new Snowflake(25, 25);
  }

  size(800,600);
}

void draw(){
  background(0);
  for(int i = 0 ; i < numSnowflakes; i++){
    snowflakes[i].descend();
    snowflakes[i].update();  
  }
}
class Snowflake{
  float imgWidth;
  float imgHeight;
  PVector pos;
  PVector vel;
  final float firstXPos;

  float a = 0.0;
  float angularVel = 0.01;

  float x;
  float amp;
  float period;

  Snowflake(float xWidth, float yHeight){
    imgWidth = xWidth;
    imgHeight = yHeight;
    pos = new PVector(random(width), 0);
    vel = new PVector(0,1);
    firstXPos = this.pos.x;
  }
  void descend(){
    amp = 75;  
    period = 200;

    x = amp * sin((frameCount/period) * TWO_PI);
    // enter local coordinate system #1
    pushMatrix();
    // move to flake position
    translate(firstXPos,this.pos.y);
      // enter local coordinate system #2
      pushMatrix();
        // move to updated (oscillated) x position
        translate(x, this.pos.y);
        // rotated from translated position (imageMode(CENTER) helps rotate around centre)
        rotate(frameCount * 0.1);
        // render the image at it's final transformation
        image(snowflakeImg,0,0, imgWidth, imgHeight);
      popMatrix();
    popMatrix();

    //creating a line for oscillation reference
    //translate(firstXPos, this.pos.y);
    //stroke(255);
    //line(0,0,x,y);

}
  void update(){
    pos.add(vel);
    a += angularVel;
  }

}

You should also check out Daniel Shiffman's Snowfall coding challenge . Even though it's p5.js the same logic can be easily applied in Processing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM