yoppa.org


SFC – デザインとプログラミング 2017

生成的な形をつくる – Processing オブジェクト指向プログラミング入門

今回はProcessingで生成的(Generative)な形態を生みだすにはどうすればよいのか、試行錯誤しながら実験していきます。まず初めに、コードを用いた生成的な表現の実例をいくつか紹介した後、実際にProcessingでプログラミングしていきます。

まず始めに、完全にランダムな確率で動きまわる「ランダムウォーク」な動きをする点の動きをつくり、その軌跡を描いてみます。次にこのランダムな動きを増殖させていきます。増殖の際に今回は全てを一つのプログラムに書くのではなく、それぞれの点を細かなプログラムで実装し、その小さなプログラム達を組合せることで一つの機能を生みだすような設計にします。この小さなプログラムを「オブジェクト (Object)」と呼び、オブジェクトを構成単位にしてプログラムを作成していく手法を、オブジェクト指向プログラミング (OOP) と呼びます。このOOPの考え方は今後も重要な内容となってきますので、実例を通して確実に理解していきましょう。

スライド資料

サンプルコード

サンプル1: 先週の復習

PVector location;
PVector velocity;
void setup() {
  size(800, 600);
  frameRate(60);
  location = new PVector(width/2, height/2);
  velocity = new PVector(random(-10, 10), random(-10, 10));
}

void draw() {
  background(0);

  location.add(velocity);

  noStroke();
  fill(0, 127, 255);
  ellipse(location.x, location.y, 20, 20);

  if (location.x < 0 || location.x > width) {
    velocity.x = velocity.x * -1;
  }
  if (location.y < 0 || location.y > height) {
    velocity.y = velocity.y * -1;
  }
}

サンプル2: ランダムウォーク基本

PVector location;
PVector velocity;
void setup() {
  size(800, 600);
  frameRate(60);
  location = new PVector(width/2, height/2);
}

void draw() {
  background(0);
  velocity = new PVector(random(-1, 1), random(-1, 1));
  location.add(velocity);

  noStroke();
  fill(0, 127, 255);
  ellipse(location.x, location.y, 20, 20);
}

サンプル3: ランダムウォークによる軌跡

PVector location;
PVector velocity;
void setup() {
  size(800, 600);
  frameRate(60);
  location = new PVector(width/2, height/2);
  velocity = new PVector();
  background(0);
}

void draw() {
  velocity.x = random(-1, 1);
  velocity.y = random(-1, 1);
  location.add(velocity);
  noStroke();
  fill(0, 127, 255);
  ellipse(location.x, location.y, 2, 2);
}

サンプル4: ランダムウォークによる軌跡 (10倍速)

PVector location;
PVector velocity;
void setup() {
  size(800, 600);
  frameRate(60);
  location = new PVector(width/2, height/2);
  velocity = new PVector();
  background(0);
}

void draw() {
  for (int i = 0; i < 10; i++) {
    velocity.x = random(-1, 1);
    velocity.y = random(-1, 1);
    location.add(velocity);
    noStroke();
    fill(0, 127, 255, 31);
    ellipse(location.x, location.y, 2, 2);
  }
}

サンプル5: ランダムウォーク・オブジェクト

Walker walker;

void setup() {
  size(800, 600);
  frameRate(60);
  
  walker = new Walker();
  
  background(0);
}

void draw() {
  walker.draw();
}

class Walker {
  PVector location;
  PVector velocity;

  Walker() {
    location = new PVector(width/2, height/2);
    velocity = new PVector();
  }

  void draw() {
    for (int i = 0; i < 10; i++) {
      velocity.x = random(-1, 1);
      velocity.y = random(-1, 1);
      location.add(velocity);
      noStroke();
      fill(0, 127, 255, 31);
      ellipse(location.x, location.y, 2, 2);
    }
  }
}

サンプル6: ランダムウォーク・オブジェクトの配列 (10個)

int NUM = 10;
Walker[] walker = new Walker[NUM];

void setup() {
  size(800, 600);
  frameRate(60);

  for (int i = 0; i < NUM; i++) {
    walker[i] = new Walker();
  }

  background(0);
}

void draw() {
  for (int i = 0; i < NUM; i++) {
    walker[i].draw();
  }
}

class Walker {
  PVector location;
  PVector velocity;

  Walker() {
    location = new PVector(width/2, height/2);
    velocity = new PVector();
  }

  void draw() {
    for (int i = 0; i < 10; i++) {
      velocity.x = random(-1, 1);
      velocity.y = random(-1, 1);
      location.add(velocity);
      noStroke();
      fill(0, 127, 255, 15);
      ellipse(location.x, location.y, 2, 2);
    }
  }
}

サンプル6: ランダムウォーク・オブジェクトの配列 (100個)

int NUM = 100;
Walker[] walker = new Walker[NUM];

void setup() {
  size(800, 600);
  frameRate(60);

  for (int i = 0; i < NUM; i++) {
    walker[i] = new Walker();
  }

  background(0);
  blendMode(ADD);
}

void draw() {
  for (int i = 0; i < NUM; i++) {
    walker[i].draw();
  }
}

class Walker {
  PVector location;
  PVector velocity;

  Walker() {
    location = new PVector(width/2, height/2);
    velocity = new PVector();
  }

  void draw() {
    for (int i = 0; i < 10; i++) {
      velocity.x = random(-1, 1);
      velocity.y = random(-1, 1);
      location.add(velocity);
      noStroke();
      fill(0, 127, 255, 5);
      ellipse(location.x, location.y, 2, 2);
    }
  }
}

サンプル7: ランダムウォーク・オブジェクトの配列 (2000個 + 画面効果)

int NUM = 2000;
Walker[] walker = new Walker[NUM];

void setup() {
  size(1920, 1200, P3D);
  frameRate(60);
  noCursor();

  for (int i = 0; i < NUM; i++) {
    walker[i] = new Walker();
  }

  background(0);
}

void draw() {
  blendMode(BLEND);
  fill(0, 15);
  rect(0, 0, width, height);
  for (int i = 0; i < NUM; i++) {
    walker[i].draw();
  }
}

class Walker {
  PVector location;
  PVector velocity;

  Walker() {
    location = new PVector(width/2, height/2);
    velocity = new PVector();
  }

  void draw() {
    for (int i = 0; i < 4; i++) {
      velocity.x = random(-1, 1);
      velocity.y = random(-1, 1);
      location.add(velocity);
      noStroke();
      blendMode(ADD);
      fill(15, 63, 255);
      ellipse(location.x, location.y, 2, 2);
    }
  }
}