yoppa.org


メディア芸術の基礎 2018 – 東京工科大学

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

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

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

スライド資料

サンプルプログラム

ランダムウォーク (クラス無し)

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() {
  //描画設定
  noStroke();
  fill(255, 31);
  //速度を設定
  velocity.x = random(-1, 1);
  velocity.y = random(-1, 1);
  location.add(velocity);
  //円を描く
  ellipse(location.x, location.y, 2, 2);
}

ランダムウォーク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() {
  //描画設定
  noStroke();
  fill(255, 31);
  for (int i = 0; i < 10; i++) {
    //速度を設定
    velocity.x = random(-1, 1);
    velocity.y = random(-1, 1);
    location.add(velocity);
    //円を描く
    ellipse(location.x, location.y, 2, 2);
  }
}

Walkerクラスによるランダムウォーク

//Walkerクラスのオブジェクトの宣言
Walker walker;

void setup() {
  size(800, 600);
  frameRate(60);
  //クラスをインスタンス化
  walker = new Walker();
  background(0);
}

void draw() {
  //Walkerクラスのdraw()メソッドを実行
    noStroke();
    fill(255, 31);
  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);
      ellipse(location.x, location.y, 2, 2);
    }
  }
}

Walkerクラスの配列 (10個)

//Walkerクラスのオブジェクトの宣言
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() {
  //色の設定
  noStroke();
  fill(255, 31);
  //配列の数だけ描画
  for (int i = 0; i < NUM; i++) {
    walker[i].draw();
  }
}

//Walkerクラス
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);
      ellipse(location.x, location.y, 2, 2);
    }
  }
}

Walkerクラスの配列 (100個)

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

void setup() {
  size(1280, 720);
  frameRate(60);
  //Walker配列の初期化
  for (int i = 0; i < NUM; i++) {
    walker[i] = new Walker();
  }
  //背景
  background(0);
}

void draw() {
  //画面をフェードさせる
  blendMode(BLEND);
  fill(0, 5);
  rect(0, 0, width, height);
  //色の設定
  noStroke();
  blendMode(ADD);
  fill(255, 31);
  //Walker配列を描画
  for (int i = 0; i < NUM; i++) {
    walker[i].draw();
  }
}

//Walkerクラス
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);
      rect(location.x, location.y, 2, 2);
    }
  }
}