次のスケッチは、画面上を1個のキャラクタが動くプログラムである。
float x, y, dx, dy, d; int c;
void setup(){ size( 400, 300 ); x = -1; y = 0; dx = 0; dy = 0; d = 1; c = #0000f0; } void draw(){ background( 0 ); fill( c ); rect( x, y, 40, 60 ); fill( 255 ); ellipse( x + 15, y + 20, 10, 15 ); ellipse( x + 25, y + 20, 10, 15 ); fill( 0 ); ellipse( x + 15 + dx * d, y + 20 + dy * d, 5, 5 ); ellipse( x + 25 + dx * d, y + 20 + dy * d, 5, 5 ); x = x + dx; y = y + dy; if( x<0 || x>width || y<0 || y>height ){ x = random( 10, width-10 ); y = random( 10, height-10 ); dx = floor( random(4) ) - 1.5; dy = floor( random(4) ) - 1.5; } if( frameCount % 60 == 0 ) d = 1; if( frameCount % 60 == 40 ) d = -1; }
キャラクタの位置はx, y、動く方向はdx, dy、目の向きはdで保持されている。 また、キャラクタの色はcに保持されている。なお、#0000f0はR,G,Bの値を16進数で 並べたものであり、少し暗い青を表す。 もっと複雑なプログラムになると、それぞれの変数が何に関係しているのかがわかりにくくなる。そこで、これらの属性をもつキャラクタを一つのまとまりとして定義してみる。 そのための仕組みがクラスである。 次の例はMonsterという名前のクラスを定義している。
class Monster{ float x, y, dx, dy, d; int c; Monster(){ x = -1; y = 0; dx = 0; dy = 0; d = 1; c = #0000f0; } void move(){ fill( c ); rect( x, y, 40, 60 ); fill( 255 ); ellipse( x + 15, y + 20, 10, 15 ); ellipse( x + 25, y + 20, 10, 15 ); fill( 0 ); ellipse( x + 15 + dx * d, y + 20 + dy * d, 5, 5 ); ellipse( x + 25 + dx * d, y + 20 + dy * d, 5, 5 ); x = x + dx; y = y + dy; if( x<0 || x>width || y<0 || y>height ){ x = random( 10, width-10 ); y = random( 10, height-10 ); dx = floor( random(4) ) - 1.5; dy = floor( random(4) ) - 1.5; } if( frameCount % 60 == 0 ) d = 1; if( frameCount % 60 == 40 ) d = -1; } }
最初のclass MonsterでMonsterという名前のクラスを宣言する。これで、Monsterはintやfloatと同じように扱える。ただし、
Monster m;
のように、Monster型の変数mを宣言するだけではなく、
m = new Monster();
のようにnewを使ってその実体(インスタンス)を構築しなければならない。 次の
float x, y, dx, dy, d; int c;
でクラスの属性(プロパティという)を定義している。これらの属性はクラスの実体ごとに割り当てられていて、mというMonster型のクラスのインスタンスのプロパティxはm.xとして表される。m.xはfloat型の変数と同様に読み書きできる。
Monster(){ ... }
は、new Monster()でインスタンスを作成するときに実行され、初期設定などを行う。これをコンストラクタという。この例では、位置と方向を設定している。
void move(){ ... }
はメソッドと呼ばれていて、これはm.move()という形で呼び出されたときに、mのプロパティを使ってその内容が実行される。この例では、キャラクタを描き、動かしている。 この定義を用いて、最初のスケッチを書き直すと、次のようになる。
Monster m; void setup(){ size( 400, 300 ); m = new Monster(); } void draw(){ background( 0 ); m.move(); } class Monster{ float x, y, dx, dy, d; int c; Monster(){ x = -1; y = 0; dx = 0; dy = 0; d = 1; c = #0000f0; } void move(){ fill( c ); rect( x, y, 40, 60 ); fill( 255 ); ellipse( x + 15, y + 20, 10, 15 ); ellipse( x + 25, y + 20, 10, 15 ); fill( 0 ); ellipse( x + 15 + dx * d, y + 20 + dy * d, 5, 5 ); ellipse( x + 25 + dx * d, y + 20 + dy * d, 5, 5 ); x = x + dx; y = y + dy; if( x<0 || x>width || y<0 || y>height ){ x = random( 10, width-10 ); y = random( 10, height-10 ); dx = floor( random(4) ) - 1.5; dy = floor( random(4) ) - 1.5; } if( frameCount % 60 == 0 ) d = 1; if( frameCount % 60 == 40 ) d = -1; } }
クラスの配列も用意されている。new Monster[4]で、「入れ物だけの」配列を用意し、
for( int i=0; i<4; i++ ) m[i] = new Monster();
で、Monsterのインスタンスを作成して、m[i]に格納する。
Monster m[]; void setup(){ size( 400, 300 ); m = new Monster[4]; for( int i=0; i<4; i++ ) m[i] = new Monster(); } void draw(){ background( 0 ); for( int i=0; i<4; i++ ) m[i].move(); } class Monster{ float x, y, dx, dy, d; int c; ... 以下、上の例と同じ }