いままで度々ボールを動かしてきた.
ボールを動かすには,位置と速度が必要なため,ボール一つを動かすためには,計4つの変数が必要になる.
float x; float y; float vx; float vy;
動かすボールが数個であれば,4つの変数のセットをボールの個数分追加すればよい.しかし,数十個,数百個で同じことをすれば,たちまち変数の数が爆発的に増える.これではプログラムは長ったらしいし,読みづらい.
float x1; float y1; float vx1; float vy1; float x2; float y2; float vx2; float vy2; ... float x100; float y100; float vx100; float vy100;
そこで,次のように独自にボールの型を作って,以下のように変数が作れればプログラムはスッキリする(そもそも配列を使うべきだがとりあえずその話は置いておく).
ボール ball0; ボール ball1; ... ボール ball100;
今回はこのように独自の型を作るためにクラスという仕組みを学ぶ.詳しい話はWebの資料に譲ることにして,さっそくクラスを導入したプログラムを見ていく.
Ball ball0;
final float GRAVITY = 9.8 / 60;
final float ELAS = 0.98;
void setup(){
size(500, 500);
ball0 = new Ball();
ball0.x = width / 2;
ball0.y = height / 2;
ball0.vx = 10;
ball0.vy = -10;
ball0.d = 50;
}
void draw(){
background(255, 255, 255);
moveBall(ball0);
drawBall(ball0);
}
void moveBall(Ball b){
b.x += b.vx;
b.vy += GRAVITY;
b.y += b.vy;
if (b.x < (b.d / 2)){
b.x = b.d / 2;
b.vx = ELAS * -b.vx;
}
if (b.x > (width - (b.d / 2))){
b.x = width - (b.d / 2);
b.vx = ELAS * -b.vx;
}
if (b.y > height - (b.d / 2)){
b.y = height - (b.d / 2);
b.vy = ELAS * -b.vy;
}
}
void drawBall(Ball b){
ellipse(b.x, b.y, b.d, b.d);
}
class Ball{
float x;
float y;
float vx;
float vy;
float d;
}
まず1行目,先ほどの
ボール ball0;
を実際にプログラムにしている.普通プログラムに日本語は使わないのでボールを表す型をBallとしている.
Ball ball0;
では,Ball型はどこで定義されているかというと下部,
class Ball{
float x;
float y;
float vx;
float vy;
float d;
}
である.このサンプルでは一番下にしているが,他の関数やクラスの{}内でなければ位置はどこでもよい.まずclass Ballで「これからBall型を定義するぞ」となり続く{}内にBall型はどのような値(属性)を持つかを記述する.属性は変数と同じように
型 属性の名前;
とする.
ここではプログラムの見やすさを考えてBall型に直径の属性dも持たせた.
Ball型の変数は配列と同じように参照型であるので,
Ball ball0;
だけでは使うことができない.
ball0 = new Ball();
ではじめて{}内の属性(x,y,vx,vy,d)が使えるようになる.newでメモリ内に作られた実体をインスタンスと呼ぶ.
各属性(x,y,vx,vy,d)を使用するには,
クラス型の変数.属性
と書く.サンプルプログラムでは,
ball0.x = width / 2;
などである.ピリオド(.)は手っ取り早く日本語で言い換えれば
ball0のx属性 = width / 2;
といった具合である.ピリオド(.)は正式には演算子の一種でドット演算子と呼ばれる.
Ball型(クラス)を使えばボールを増やしたとしても,
Ball ball0;
Ball ball1;
final float GRAVITY = 9.8 / 60;
final float ELAS = 0.98;
void setup(){
size(500, 500);
ball0 = new Ball();
ball0.x = width / 2;
ball0.y = height / 2;
ball0.vx = 10;
ball0.vy = -10;
ball0.d = 50;
ball1 = new Ball();
ball1.x = width / 2;
ball1.y = height / 2;
ball1.vx = -10;
ball1.vy = 10;
ball1.d = 20;
}
void draw(){
background(255, 255, 255);
moveBall(ball0);
drawBall(ball0);
moveBall(ball1);
drawBall(ball1);
}
//moveBall関数以下は変更ないので省略
このように1変数=1つのボールに対応するので,プログラムの読みやすさが向上する.