Processingでアニメーションを作成する

# ■基本編

```java
$ cat sketch_211223a.pde
int degree = 0;
int r = 100;

void setup(){
  size(300,300);
  frameRate(24);
  smooth();
}

void draw(){
  background(0);
  degree += 2;
  float x = width/2 + r * cos(degree*PI/180.0);
  float y = height/2 + r * sin(degree*PI/180.0);
  translate(x,y);
  rotate(-degree * PI/15.0);

  // These below are relative coorinates from the translated origin
  // In this case, (0,0) is the center for rotation
  rect(-10,-10,20,20);

  /*** Save into PNG ***/
  saveFrame("frames/######.png");
}
```

上記を実行すると以下のPNGが連番フレームで作成される。

```sh
$ ls *.png | (head; echo; tail)
000001.png
000002.png
000003.png
000004.png
000005.png
000006.png
000007.png
000008.png
000009.png
000010.png

000316.png
000317.png
000318.png
000319.png
000320.png
000321.png
000322.png
000323.png
000324.png
000325.png

```

この連番PNGファイルをffmpegで動画作成する。

```zsh
$ ffmpeg -r 30 -i %06d.png -vcodec libx264 -pix_fmt yuv420p -r 60 out.mp4
```

動画は添付できないのでイメージのみwww
![000325.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182287/6cdbb5e7-e592-7934-be6d-47e8dc946754.png)

# ■応用編その１

これはProcessingのご本家サイトからサンプルソースをベースに遊んでみたもの：

```java
$ cat Tree.pde
float theta;
float a;
int direction;
int bCount = 120;

void setup() {
    size(640, 480);
    smooth();
    a = 0;
    direction = 1;
}

void draw() {
    background(0);
    frameRate(24);
    stroke(255);
    theta = radians(a);
    translate(width/2,height);
    line(0,0,0,-240);
    translate(0,-240);
    branch(bCount);
    a += direction;

    if( a < 0 || a > 1280 ) {
        direction = -1 * direction;
    }

    /*** Save into PNG ***/
    saveFrame("frames/######.png");

}

void branch(float h) {
    // Each branch will be 2/3rds the size of the previous one
    h *= 2.0/3;

    // All recursive functions must have an exit condition!!!!
    // Here, ours is when the length of the branch is 2 pixels or less

    if (h > 2) {
        pushMatrix();    // Save the current state of transformation (i.e. where are we now)
        rotate(theta);   // Rotate by theta
        line(0, 0, 0, -h);  // Draw the branch
        translate(0, -h); // Move to the end of the branch
        branch(h);       // Ok, now call myself to draw two new branches!!
        popMatrix();     // Whenever we get back here, we "pop" in order to restore the previous matrix state
        // Repeat the same thing, only branch off to the "left" this time!
        pushMatrix();
        rotate(-theta);
        line(0, 0, 0, -h);
        translate(0, -h);
        branch(h);
        popMatrix();
    }

}

```
これまた、動画は添付できないのでイメージのみwww

![000061.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182287/99a69f9d-6d7f-2f2c-2789-89c98170e9ff.png)

# ■応用編その２
これは鎖をイメージしたこれ私の勝手オリジナルw

```java
ElementManager em;

void setup(){
  em = new ElementManager();
  size(640,640);
  stroke(255);
  smooth();
  background(0);
}

void draw(){
  background(0);
  translate(width/2, height/2);
  scale(1,-1);
  em.move();
  em.renderAll();

  /*** Save into PNG ***/
  saveFrame("frames/######.png");
}

class Element{
  float x;
  float y; 
  Element follower = null;

  public Element( float x, float y ){
    this.x = x;
    this.y = y; 
  }
}

class ElementManager{
  final int NUM_OF_ELEMENTS = 128;
  ArrayList al;
  float len = 25;
  int angle = 0;
 
  ElementManager(){
    al = new ArrayList();
    for(int i=0;i<NUM_OF_ELEMENTS;i++){
      al.add(new Element(-len*i,0));
    }
    // println(al.size());
  }

  public int getSize(){
    return al.size(); 
  }

  public void move(){
    angle += 1;
    // The 1st one moves freewheelingly
    Element e1st = (Element)al.get(0);
    e1st.x += -10*cos(angle*PI/90.0);
    e1st.y += 5*cos(angle*PI/180.0);

    // println( e1st.y );

    for(int i=1;i<al.size();i++){
      Element e1 = (Element)al.get(i-1);
      Element e2 = (Element)al.get(i);

      // get unit vertor
      float vx = e1.x - e2.x;
      float vy = e1.y - e2.y;
      float distance = sqrt(vx*vx + vy*vy);
      vx /= distance;
      vy /= distance;

      // set new location
      e2.x = e1.x - vx * len;
      e2.y = e1.y - vy * len;   
    }
  }

  public void renderAll(){
    for(int i=0;i<al.size()-1;i++ ){
      Element e1 = (Element)al.get(i);
      Element e2 = (Element)al.get(i+1);
      rectMode(CENTER);
      rect(e1.x, e1.y, 3, 3);
      rect(e2.x, e2.y, 3, 3);
      line(e1.x, e1.y, e2.x, e2.y);
    }
  }

}
```

![000057.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182287/173c1e94-57c9-2dc8-b38a-0def014e6942.png)
![000184.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182287/a1852d66-2362-1ceb-87e9-5a15b486fbf2.png)
![000232.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182287/09c87905-9d58-4cda-5c0e-8f7d5a446e15.png)

# ■応用編その３

```java
// $ astyle --delete-empty-lines --mode=java --indent=spaces=2 Chain.pde


// $ cat Chain.pde
ElementManager em;

void setup() {
  em = new ElementManager();
  size ( 1500, 640 );
  stroke ( 255 );
  smooth();
  background ( 0 );
}

void draw() {
  background ( 0 );
  translate ( width/2, height/2 );
  scale ( 1,-1 );
  em.move();
  em.renderAll();
  /*** Save into PNG ***/
  // saveFrame ( "frames/######.png" );
}

class Element {

  float x;
  float y;

  // Element follower = null;
  public Element ( float x, float y ) {
    this.x = x;
    this.y = y;
  }

}

class ElementManager {

  final int NUM_OF_ELEMENTS = 256;
  ArrayList al;
  float len = 25;
  int angle = 0;

  ElementManager() {
    al = new ArrayList();
    for ( int i=0; i<NUM_OF_ELEMENTS; i++ ) {
      al.add ( new Element ( -len*i,0 ) );
    }
    // println(al.size());
  }

  public int getSize() {
    return al.size();
  }

  public void move() {
    angle += 1;
    // The 1st one moves freewheelingly
    Element e1st = ( Element ) al.get ( 0 );
    e1st.x += 3*sin ( angle*PI/320.0 );
    e1st.y += 5*cos ( angle*PI/180.0 );
    // println( e1st.y );
    for ( int i=1; i<al.size(); i++ ) {
      Element e1 = ( Element ) al.get ( i-1 );
      Element e2 = ( Element ) al.get ( i );
      // get unit vertor
      float vx = e1.x - e2.x;
      float vy = e1.y - e2.y;
      float distance = sqrt ( vx*vx + vy*vy );
      vx /= distance;
      vy /= distance;
      // set new location
      e2.x = e1.x - vx * len;
      e2.y = e1.y - vy * len;
    }
  }

  public void renderAll() {
    for ( int i=0; i<al.size()-1; i++ ) {
      Element e1 = ( Element ) al.get ( i );
      Element e2 = ( Element ) al.get ( i+1 );
      rectMode ( CENTER );
      rect ( e1.x, e1.y, 3, 3 );
      rect ( e2.x, e2.y, 3, 3 );
      line ( e1.x, e1.y, e2.x, e2.y );
    }
  }

}

```
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182287/0af41db4-50be-43b0-1356-5111dd220eee.png)


# ■備忘録
- https://sites.google.com/site/havingjoyfuldayswithprocessing/home/1basics/translation
- https://p5js.org/get-started/