5.3.5 クラスファイルの作成
ここでは、他のプログラムにも再利用できるようにCircleクラス用のファイルを作成します。コードは【リスト5.3-b】をコピーし、そこからCircleクラスの部分だけを別ファイル(Circle.pde)にします。
Processingの画面右上のボタンから「New Tab」をクリックします【図5.3-g】。
さらに、この新しいタブの名前をクラス名であるCircleにして「OK」します【図5.3-h】。
すると、新しいファイルが表示されます【図5.3-i】。
Circleクラスをファイルにする場合には、ファイル名は必ずクラス名と同じになっていなければいけません。このサンプルでは、次のふたつのファイルに分けました【図5.3-j】。
・【リスト5.3-f】フォルダ
・oop_class.pde(実行ファイル)
・Circle.pde(クラスファイル)
この新しいCircleクラスのファイルに、クラスの定義の部分だけカット&ペーストして保存します。実行ファイル(oop_class.pde)にクラス定義のコードを残さないでください。
ファルダ構成は【図5.3-k】のようになります。
これでクラスファイルの作成は終了です。一度クラスファイルを作ったら、それ以降はSketchメニュー > Add File…で他のプログラムで再利用することができます。
5.3.6 クラスの継承とは
ここからは、オブジェクトに柔軟性と拡張性を与えるための機能である「継承」を学びます。
継承は、簡単に言ってしまえば「遺伝」です。親から子が産まれる時に親のDNAを引き継ぎますが、完全な親のコピーではありません。新たな能力の獲得がある場合もありますし、それぞれ違った個性が育ちます。
このように、クラスがひな型だとすると、そのひな型の属性を引き継ぎなおかつ新しい属性を付加したクラスを作成することを「継承」と呼びます。
5.3.7 クラスの合成
クラスの継承の前に、複数のクラスを合成したクラスを作ってみます。サンプルでは、正方形と円の複合体が作成されます。
まず、前述の「oop_class.pde」を「oop_circle_rect」として別名保存してください。さらにこの他にクラスファイルを3つ作るので、ファイルは全部で4つになります。
・【リスト5.3-g】フォルダ
・oop_circle_rect.pde(実行ファイル – 新規)
・Circle.pde(クラスファイル – 再利用)
・Rect.pde(クラスファイル – 新規)
・CircleRect.pde(クラスファイル – 新規)
それでは、一つずつ作っていきましょう。まず、Rectクラスを作ります。
Rect.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class Rect { float x, y; //x座標、y座標 float rad; //正方形の回転角度 int rSize; //正方形のサイズ float velocity; //移動スピード //コンストラクタ Rect(float _y, int _rSize, float _velocity) { rectMode(CENTER); //基準点を正方形の中心にする x = 0.0; y = _y; rad = 0.0; rSize = _rSize; velocity = _velocity; } //更新メソッド void update() { noFill(); x += velocity; //velocity分のx座標を移動 if (x > width) { //円のx座標がウィンドウの幅を超えたら、 x = 0; //位置を0に戻す } } //表示メソッド void display() { pushMatrix(); //座標を保存 translate(x, y); //基準点を移動 rotate(rad); //回転 rect(0, 0, rSize, rSize); //正方形を描画 popMatrix(); //座標を復帰 rad += 0.01; } } |
さらに、CircleクラスとRectクラスを合成した、CircleRectクラスを作成します。
CircleRect.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class CircleRect { Circle myCircle; //インスタンス Rect myRect; //コンストラクタ CircleRect(float _y, int _eSize, int _rSize, float _velocity) { //Circleクラスのインスタンスを作成 myCircle = new Circle(_y, _eSize, _velocity); //Rectクラスのインスタンスを作成 myRect = new Rect(_y, _rSize, _velocity); } void display() { myCircle.update(); //更新と表示 myCircle.display(); myRect.update(); myRect.display(); } } |
CircleRectクラスの中でCircleクラスとRectクラスのインスタンスを作成しています。
このCircleRectクラスを最終的に、opp_circle_rectファイル(実行ファイル)内でインスタンス化します。
opp_circle_rect.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | CircleRect cr1, cr2; //CircleRectクラスのインスタンスを宣言 void setup() { size(400, 400); stroke(0); //引数はCircleRect(y座標, ellipseのサイズ、rectのサイズ、スピード) cr1 = new CircleRect(100, 5, 20, 0.1); //オブジェクトを作成 cr2 = new CircleRect(300, 40, 60, 0.3); //オブジェクトを作成 } void draw() { background(255); //背景は白 cr1.display(); //c1, c2インスタンスのupdateメソッドを実行 cr2.display(); } |
5.3.8 クラスの継承
さて、ここからがクラスの継承の本番です。Circleクラスはそのまま使いますが、このクラスを継承して色彩の機能を持たせたColorCircleクラスを作成します。最終的には別々の色彩を持った円を作成します。
作成するファイルは次の3つです。
・【リスト5.3-h】フォルダ
・oop_color_circle.pde(実行ファイル – 新規)
・Circle.pde(クラスファイル – 再利用)
・ColorCircle.pde(クラスファイル – 新規)
ColorCircle.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //Circleクラスを継承したColorCircleクラス class ColorCircle extends Circle { color eColor; //色彩の変数であるeColorを宣言 //コンストラクタ ColorCircle (float _y, int _eSize, float _velocity, color _eColor) { //親クラス(Circleクラス)のコンストラクタを実行する super(_y, _eSize, _velocity); eColor = _eColor; } //更新メソッド void update() { super.update(); //親クラス(Circleクラス)のupdate()メソッドを実行 } //色を設定して表示するメソッド void displayColor() { fill(eColor); //色彩を設定 super.display(); //親クラス(Circleクラス)のdisplay()メソッドを実行 } } |
このクラスを宣言することによって、円の色を定義することが可能になりました。
この場合のCircleクラスを親クラス(スーパークラス)、ColorCircleクラスを子クラス(サブクラス)と呼びます。親子の関係となっているということですね。
そして、最終的にoop_color_circleファイルでColorCircleクラスのインスタンスを作成します。
oop_color_circle.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ColorCircle c1, c2; //ColorCircleクラスのインスタンスを宣言 void setup() { size(400, 400); noStroke(); fill(0); //黒で描画 //インスタンス作成 c1 = new ColorCircle(100, 10, 1.0, color(255, 0, 0)); c2 = new ColorCircle(300, 40, 3.5, color(0, 0, 255)); } void draw() { background(255); //背景は白 //c1インスタンスのクラスである、ColorCircleクラスのupdate()と //displayColor()メソッドを実行 c1.update(); c1.displayColor(); c2.update(); c2.displayColor(); } |
5.3.9 クラスのカスタマイズ
それではもう少しクラスの作成に慣れるためにoop_color_circleサンプルを元に、キーボードの矢印キーでオブジェクトのスピードが変わるように書き換えてみましょう。まずは、Circleクラスにスピードを設定するメソッド(setVelocity)を追加します。
・【リスト5.3-i】フォルダ
・oop_circle_velocity.pde(実行ファイル – 新規)
・Circle.pde(クラスファイル – メソッド追加)
・ColorCircle.pde(クラスファイル – メソッド追加)
Circle.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | //Circleクラスの宣言 class Circle { float x, y, eSize, velocity; //初期化用メソッド(コンストラクタ) Circle (float _y, int _eSize, float _velocity) { x = 0.0; //x座標の初期値は0.0 y = _y; //y座標の初期値はインスタンスの引数 eSize = _eSize; //velocityの初期値はインスタンスの引数 velocity = _velocity; } //円の位置を更新するメソッド void update() { x += velocity; //velocity分のx座標を移動 if (x > width) { //円のx座標がウィンドウの幅を超えたら、 x = 0; //位置を0に戻す } } void display() { ellipse(x, y, eSize, eSize); //円を描く } //スピードを設定するメソッド void setVelocity(float _velocity) { velocity += _velocity; //0未満にはならないようにする if (velocity < 0.0) velocity = 0.0; } } |
そして、ColorCircleクラスに、スピードを変えるfaster(), slower()メソッドを追加します。
ColorCircle.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | //Circleクラスを継承したColorCircleクラス class ColorCircle extends Circle { color eColor; //色彩の変数であるeColorを宣言 //コンストラクタ ColorCircle (float _y, int _eSize, float _velocity, color _eColor) { //親クラス(Circleクラス)のコンストラクタを実行する super(_y, _eSize, _velocity); eColor = _eColor; } //更新メソッド void update() { super.update(); //親クラス(Circleクラス)のupdate()メソッドを実行 } //色を設定して表示するメソッド void displayColor() { fill(eColor); //色彩を設定 super.display(); //親クラス(Circleクラス)のdisplay()メソッドを実行 } //スピードを速くするメソッド void faster() { //親クラス(Circleクラス)のsetvelocity()に0.5を渡す super.setVelocity(0.5); } //スピードを遅くするメソッド void slower() { //親クラス(Circleクラス)のsetvelocity()に-0.5を渡す super.setVelocity(-0.5); } } |
最後に、oop_circle_velocityには、keyPressed()の機能を追加します。
oop_circle_velocity.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | //ColorCircleクラスのインスタンスを宣言 ColorCircle c1, c2; void setup() { size(400, 400); smooth(); //図形の輪郭をきれいに描画 noStroke(); fill(0); //黒で描画 //インスタンス作成 c1 = new ColorCircle(100, 10, 1.0, color(255, 0, 0)); c2 = new ColorCircle(300, 40, 3.5, color(0, 0, 255)); } void draw() { background(255); //背景は白 //c1インスタンスのクラスである、ColorCircleクラスのupdate()と //displayColor()メソッドを実行 c1.update(); c1.displayColor(); c2.update(); c2.displayColor(); } void keyPressed() { if (key == CODED) { if (keyCode == UP) { //上に動く c1.faster(); c2.faster(); } else if (keyCode == DOWN) { //下に動く c1.slower(); c2.slower(); } } } |
もちろん、このサンプルを配列化することもできます。このことによって、たくさんの自律的なオブジェクトを作成することができます。
・【リスト5.3-j】フォルダ
・oop_circle_velocity_array.pde(実行ファイル – 新規)
・Circle.pde(クラスファイル – 再利用)
・ColorCircle.pde(クラスファイル – 再利用)
Circle.pdeとColorCircle.pdeは【リスト5.3-i】のサンプルと同じなので、省略します。
oop_circle_velocity_array.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | //ColorCircleクラスのインスタンスを100個宣言 ColorCircle[] c = new ColorCircle[100]; void setup() { size(400, 400); smooth(); //図形の輪郭をきれいに描画 noStroke(); fill(0); //黒で描画 for (int i = 0; i < c.length; i ++) { c[i] = new ColorCircle(i * 4, //y座標 4, //円のサイズ random(0.01, 5.0), //スピードをランダムに決定 color((int)random(255), 100, 0)); //色 } } void draw() { background(255); //背景は白 //c1インスタンスのクラスである、ColorCircleクラスのupdate()と //displayColor()メソッドを実行 for (int i = 0; i < c.length; i ++) { c[i].update(); c[i].displayColor(); } } void keyPressed() { if (key == CODED) { if (keyCode == UP) { //上に動く for (int i = 0; i < c.length; i ++) c[i].faster(); } else if (keyCode == DOWN) { //下に動く for (int i = 0; i < c.length; i ++) c[i].slower(); } } } |
Pingback: Processing触ってみた | 水玉製作所