クラス(class)を使う

クラスを使う

さて、ここまで扱ってきた丸または円を、分子をイメージした「粒子」として具体化していきましょう。

前頁のプログラムでは、粒子の「位置」や「速度」、「生成してからの時間」等が別の配列変数としてばらばらに定義されていました。

これらを粒子1個を表すデータ、「クラス」にまとめます。

Particle[] particle = new Particle[64]; //クラスの配列の宣言
int j;

void setup(){
  size(400, 400);
  background(0);
  smooth();
  noStroke();
  for(int i=0; i<64; i++){
    particle[i] = new Particle(width/2, height/2, 0, 0);
    //クラスの実体の宣言
  }
}

void draw(){
  background(0);
  for(int i=0; i<64; i++){
    if(particle[i].visible > 0){
      fill(255, 255, 255, particle[i].visible);
      ellipse(particle[i].x, particle[i].y, 40, 40);
    }
    particle[i].x = particle[i].x + particle[i].vx;
    particle[i].y = particle[i].y + particle[i].vy;
    particle[i].visible = particle[i].visible - 2;
  }
}

void mousePressed(){
  float deg;
  deg = random(2*PI);
  particle[j].x = width/2;
  particle[j].y = height/2;
  particle[j].vx = cos(deg);
  particle[j].vy = -sin(deg);
  particle[j].visible = 255;
  j = j + 1;
  if(j == 64){
    j = 0;
  }
}

class Particle{  //クラスParticleの定義
  float x; //x座標
  float y; //y座標
  float vx; //x方向の速度
  float vy; //x方向の速度
  float visible; //動き始めてからの時間

  Particle(float ix, float iy, float ivx, float ivy){
  //クラスの実体を宣言するときの処理
    x = ix;
    y = iy;
    vx = ivx;
    vy = ivy;
  }
}

このプログラムは、前頁の最後のプログラムと全く同じ動作をするはずです。

コードの後半(42行目から)で、粒子1個分のデータを表すクラス、Particleを定義しています。
これには粒子の位置や速度を表すx, y, vx, vyなどが含まれています。

クラスには、そのクラス型の変数を定義するときの初期化処理を書く必要があります。
これはクラスのブロックの中に、クラスの名前と同じ名前の関数として定義します。

クラスはnew文を使って宣言します。(10行目)

この例では、クラスの配列を使っていますので、配列の宣言が別に必要です。(1行目)

クラスの中の変数には particle[i].x というように、ピリオドでつないで変数名を書くことでアクセスできます。

クラスにメソッドを含める

クラスを使うことで、いろいろな変数(x, yなど)をばらばらに使うことを避け、粒子(particle)という単位でデータを扱うことができるようになります。

クラスの本領はさらにここから発揮されます。クラスにはデータだけでなく、メソッド(処理)を含めることもできます。上の例では

  • 粒子の表示(18~21行目)
  • 粒子の移動(22~24行目)
  • 粒子を中心に移す(29~35行目)

という処理があります。これらは粒子固有の処理なので、クラスの中に含めてしまいましょう。

Particle[] particle = new Particle[64];
int j;

void setup(){
  size(400, 400);
  background(0);
  smooth();
  noStroke();
  for(int i=0; i<64; i++){
    particle[i] = new Particle(width/2, height/2, 0, 0);
  }
}

void draw(){
  background(0);
  for(int i=0; i<64; i++){
    particle[i].display();
    particle[i].move();
  }
}

void mousePressed(){ //マウスクリック時
  particle[j].move_center();
  j = j + 1;
  if(j == 64){
    j = 0;
  }
}

class Particle{
  float x; //x座標
  float y; //y座標
  float vx; //x方向の速度
  float vy; //x方向の速度
  float visible; //動き始めてからの時間
  float r; //半径

  int R;
  int G;
  int B;

  Particle(float ix, float iy, float ivx, float ivy){
    x = ix;
    y = iy;
    vx = ivx;
    vy = ivy;
    visible = 0;
    r = 40;
    R = G = B = 255;
  }

  void display(){ //粒子の表示
    if(visible > 0){
      fill(R, G, B, visible);
      ellipse(x, y, r, r);
    }
  }

  void move(){ //粒子の移動
    x = x + vx;
    y = y + vy;
    visible = visible - 2;
  }

  void move_center(){ //粒子を中心に
    float deg;
    deg = random(2*PI);
    x = width/2;
    y = height/2;
    vx = cos(deg);
    vy = -sin(deg);
    visible = 255;
  }
}

先に挙げた3つの処理はdisplay, move, move_centerとしてクラスParticleの中に移しました。これによって、初期化(setup)と時間の経過に関する処理(draw)と、粒子に関する処理(class Particle)を明確に分けることができました。

クラス中のメソッドは
particle[i].display();
というようにして、クラス中の変数と同じように、ピリオドを付けて呼び出すことができます。(17, 18, 23行目)
(うしろの() (かっこ, かっこ閉じ)は、呼び出したものがメソッドであることを示しています。)

クラスParticleの中では、粒子のデータの処理に専念すればよいので、プログラミングは(特に多人数でプログラム開発を行う場合などに)ずっとやりやすくなります。

クラスは比較的新しい概念で、C言語やFORTRANなどでは実装されていません。
Cの改良版のC++や、java, PHPなどで使うことができます。