オブジェクト指向プログラミング

情報や機能を1つにまとめるオブジェクトについて説明します。

オブジェクト指向プログラミングは一言でいうと、様々な情報や機能を1つにまとめる記述方法です。

ここではすべてについてを詳細に説明しませんが、情報を1つにまとめて使用する例を説明します。

情報をまとめるためにオブジェクト指向プログラミングはクラス定義で特定の名前のオブジェクトを作成します。

class クラス名 {
    メンバ変数の宣言(情報)
    メソッドの定義(機能)
}

複数情報を1つにまとめる

配列で作成したコードを改造し、複数の配列情報を1つにまとめ、そこに10個の円の必要な情報を格納します。

class Circle {
  float x,y;
  int dx,dy;
  color c;
}
Circle[] ens = new Circle[10];
void setup() {
  size(500,500);
  for (int i=0; i<ens.length; i++) {
    Circle e = new Circle();
    e.x = random(25,width-25);
    e.y = random(25,height-25);
    e.dx = int(random(2,4));
    e.dy = int(random(3,5));
    e.c = color(0);
    ens[i] = e;
  }
}
void draw() {
  background(255);
  for (Circle e : ens) {
    e.x += e.dx;
    e.y += e.dy;
    if (e.x < 25 || e.x > width-25) {
      e.dx *= -1;
      e.c = color(random(255),random(255),random(255),random(128,255));
    }
    if (e.y < 25 || e.y > height-25) {
      e.dy *= -1;
      e.c = color(random(255),random(255),random(255),random(128,255));
    }
    fill(e.c);
    ellipse(e.x,e.y,50,50);
  }
}

1〜5行目で円のクラス定義を記述しています。名前はCircleで配列で持っていた各データがメンバ変数として宣言されています。

6行目でこのクラスオブジェクトを10個格納する配列を作ります。

クラスオブジェクトはその名前がデータ型となります。

9〜17行目でens配列に生成したCircleオブジェクトを格納しています。

Circleオブジェクトを生成したときに各メンバ変数に初期値を格納しています。

メンバ変数にアクセスするには「オブジェクトの変数.メンバ変数」というようにドット(.)を使って記述します。

21〜34行目でens配列から格納しているオブジェクトを1つずつ取り出して、オブジェクトが持つ情報を使って円を描画しています。

ArrayListを使えば、描画する円の数が決まってないときに、画面をマウスで押したときに円を増やすコードも効率よく記述することができます。

class Circle {
  float x,y;
  int dx,dy;
  color c;
}
ArrayList<Circle> ens = new ArrayList<Circle>();
void setup() {
  size(500,500);
}
void draw() {
  background(255);
  for (Circle e : ens) {
    e.x += e.dx;
    e.y += e.dy;
    if (e.x < 25 || e.x > width-25) {
      e.dx *= -1;
      e.c = color(random(255),random(255),random(255),random(128,255));
    }
    if (e.y < 25 || e.y > height-25) {
      e.dy *= -1;
      e.c = color(random(255),random(255),random(255),random(128,255));
    }
    fill(e.c);
    ellipse(e.x,e.y,50,50);
  }
}
void mousePressed() {
  Circle e = new Circle();
  e.x = random(25,width-25);
  e.y = random(25,height-25);
  e.dx = int(random(2,4));
  e.dy = int(random(3,5));
  e.c = color(0);
  ens.add(e);
}

6行目で配列を作成していたコードをArrayListに変更します。

初期値は円を追加したときとなるので、setup()での初期化処理を削除します。

27〜35行目でマウスを押したときに新しいCircleオブジェクトを生成し、各メンバ変数に初期値を代入したあとensリストにオブジェクトを追加します。

draw()の中は先程のコードのまま変更なしで同じ描画の動作をします。

波紋

その他の例として、マウスを押したところに波紋を描くコードを書いてみましょう。

class Ripple {
  float x,y;
  int r1=0,r2=0;
}
ArrayList<Ripple> rips = new ArrayList<>();
void setup() {
  size(500,500);
}

void draw() {
  noStroke();
  fill(0,10);
  rect(0,0,width,height);
  stroke(0,255,200);
  ArrayList<Ripple> cpy = new ArrayList<>(rips);
  for (Ripple rip : cpy) {
    if (rip.r1 != 0) rip.r1 += 2;
    if (rip.r1 > 30 || rip.r2 != 0) rip.r2 += 2;
    ellipse(rip.x,rip.y,rip.r1,rip.r1);
    ellipse(rip.x,rip.y,rip.r2,rip.r2);
    if (rip.r1 > 100) rip.r1 = 0;
    if (rip.r2 > 100) rips.remove(rip);
  }
}

void mousePressed() {
  Ripple rip = new Ripple();
  rip.x = mouseX;
  rip.y = mouseY;
  rip.r1 = 1;
  rips.add(rip);
}

1〜4行目で定義しているRippleクラスは波紋となる円のオブジェクトです。

中心の座標と、直径(円の大きさ)を2種類格納するメンバ変数を持っています。

5行目でグローバル変数としてrips変数にこのオブジェクトを格納するリストを生成しています。

26〜32行目のmousePressed()関数でマウスが押されたときにオブジェクトを生成しリストに格納します。

オブジェクト生成時にはそのときのマウス座標とr1変数に1の大きさを入れています。

15〜23行目でリストのオブジェクトを描画し波紋を表現しています。

まずは、cpy変数にrips変数のリストをコピーしています。これは、次に続くfor文の中でオブジェクトの大きさが100を超えたらripsリストから削除するためです。

コピーしないで、for文の繰り返しで使用しているリストの要素をfor文の中で削除するとエラーになるためです。

そのためdraw()関数が呼ばれるたびにリストをコピーしてその情報で波紋を描画しています。

19〜20行目で2つの塩を少しずつ大きくしながら描いて波紋を表現しています。

r2変数の大きさが100を超えたらオブジェクトをripsリストから削除します。