第3回目の Processing.js でゲームプログラミングです。
第2回から作りはじめた弾幕<風>シューティングゲーム、いよいよ今回で主役?の弾幕を出して行きたいと思います。おさらいも兼ねて、前回の最終版のソースをみてみましょう。あ、でもそのまんまだと芸がないので、ちょっと修正も入れていますよ。
size(320, 320);
frameRate(30);
noCursor(); // clear mouse cursor
}
// my ship function
void ship(int x, int y) {
stroke(255,255,255);
noFill();
triangle(x, y - 7, x - 10, y + 7, x + 10, y + 7);
if (mousePressed) {
line(x, y - 7, x, 0);
}
}
void draw() {
background(0); // clear
ship(mouseX, mouseY);
}
動作内容はまったく同じなんですが、これから弾幕の処理も追加していって、プログラムが大きくなっていきそうだったので、これまで draw関数のなかで進めていた 自機の処理を関数 ship にまとめて draw 関数の外に出してしまいました。これまでは、システムで用意されている関数を使うだけだった思うのですが、このように好きなように関数を作っていくことが出来ます。もちろん、だらだらとdraw 関数内に書いていくこともできるのですが、このように機能単位で関数を分けていくと、あとあとメンテナンスがしやすかったりしてとても便利なのです。プログラムするときは、いろんな処理をどんどん、関数に分けていきましょう。
ちなみにこういう風に機能単位で関数で分けておくと、同じようなことをするときに引数を変えて関数を呼ぶだけで、簡単に実現できます。たとえば、こんなカンジです。
いきなり自機がパワーアップしましたね (^^)
ちょっと長くなりました。いよいよ弾を出しますよ!弾は最初から、独立した関数で作っていくことにしましょうか。弾幕も1発の弾からダーゼーってことで、まずは1発、弾をだしてみることにトライしますよ!
size(320, 480);
frameRate(30);
noCursor(); // clear mouse cursor
}
// my ship function
void ship(int x, int y) {
stroke(255,255,255);
noFill();
triangle(x, y -7, x - 10, y + 7, x + 10, y + 7);
if (mousePressed) {
line(x, y - 7, x, 0);
}
}
// tama function
float tx = 160;
float ty = 0;
float r = 10;
void tama() {
ty += 10;
stroke(255, 0, 0);
ellipse(tx, ty, r, r);
if (ty > height) {
ty = 0;
tx = random(width);
}
}
void draw() {
background(0); // clear
ship(mouseX, mouseY);
tama();
}
新しく弾を動かして表示する tama 関数をつくりました。そして、tama 関数の直前には、弾の座標を保持する tx, ty という変数。そして 半径として使う r という変数を宣言しています。tama 関数は呼ばれるたびに、ty の値を 10 づつ増加させ、円を描画する ellipse 関数で、tx, ty の座標に円を描くのですね。
1秒間に30回よばれる draw 関数から、この tama 関数がよばれ、呼ばれるたびにちょっとづつ y 座標を変化させます。このことによって、弾が動いて見えるというわけです。そして、ほっておくと、画面の外にいってしまうので、画面外に出てしまったら、また ty を 0 に設定しなおすことで、またスタート地点に戻しています。そして、そのついでに、tx の座標をrandom 関数を使って、ランダム(=でたらめ)に設定しています。なので、弾がx座標を変えながら、いつまでもくるくるとたまが回っているんですね。random 関数は、ゲームでランダムになにかを出現させたり消したりする必要が有る場合、とても便利に使える関数です。
ちなみに、tx, ty という変数がなぜ、tama関数の中に入っていないのか?ちょっと不思議に思う人もいるかもしれませんが、tama 関数は draw 関数から呼ばれるたびにプログラムどおり同じ動作をしますから、このなかにこの座標をいれてしまうと、いつも同じ数字がセットされ、結局、動かない事になってしまうんですね。なので、座標はtama 関数の外で覚えておく必要があり、だから tama 関数の外で宣言したというわけです。
ようやく、ついに弾が表示できました!つぎはこの弾を沢山同時に表示することが出来れば、弾幕風になることでしょう。たくさん弾を表示するためには、それぞれの弾の分だけ、弾の座標 tx と ty が必要です。その数たるや、弾幕風というからには相当な数になることが予想に難くありません。それを想定し、変数をあらかじめたくさん宣言しておくことも不可能ではありませんが、とんでもないことになりそうです。なにかいい方法はないのでしょうか?
現代の多くのプログラム言語では、この様に同じものを沢山処理する必要がある場合、とても便利に処理することができる仕組みがあります。それは class(クラス)という機能と、array(配列)という機能で、モチロン、それらは Processing.js でも使うことができるのです。
では class はなにか?というと、簡単にいえば設計図です。設計図を作っておけば、設計図をもとに何個でも、何百個でもインスタンス(=インスタンス)を作ってくれるのです。今回は、弾を何百個もつくり、動かしていかなくてはいけませんから、まさにもってこいですね!では、早速、さっきのソースをclass を使って書き換えて見ましょう。そのバージョンが、下記のソースになります。
void setup() {
size(320, 320);
frameRate(30);
noCursor(); // clear mouse cursor
tama = new Tama(160, 0, 10);
}
// my ship function
void ship(int x, int y) {
stroke(255,255,255);
noFill();
triangle(x, y - 7, x - 10, y + 7, x + 10, y + 7);
if (mousePressed) {
line(x, y- 7 , x, 0);
}
}
// tama class
class Tama {
float tx, ty, tr;
Tama(float x, float y, float r) {
tx = x;
ty = y;
tr = r;
}
void update() {
ty += 10;
stroke(255, 0, 0);
ellipse(tx, ty, tr, tr);
if (ty > height) {
ty = 0;
tx = random(width);
}
}
}
void draw() {
background(0); // clear
ship(mouseX, mouseY);
tama.update();
}
classについて、さっきは設計図だという話をしましたが、プログラムの設計図とはどういう事なんでしょうか?この Tama クラスの場合ですが、必要なのは大きく2つあります。弾の場所と、弾をどう動かすのかということですね。では、それらが設計図に入っていれば、大丈夫なはずです。Tama class を見てもらえれると、中に tx,ty,tr という3つの変数と、Tama というclass 名と同じ関数。そして、update という関数があるのがわかると思います。
class の中に書いてある変数「クラス変数」は、クラスが作られるたびに、まとめて自動的に作られます。この機能によってどんなにたくさんの変数を使っていても、ちゃんと設計図(=クラス)に書いてさえあれば、まとめて管理することができるんですね。そして、クラスの中に書いてある関数「クラス関数」(メソッドとかいう時もあります)は、基本的にクラスの中に書いてある変数を対象として、動作します。だから、どんどん弾がふえていっても、ちゃんとそれそれの update 関数を呼んであげれば、弾はちゃんと動くというわけなんですね。
クラスとインスタンスのシンプルな図解を用意しました。参考にしてください。
クラスの名前と同じような関数は「コンストラクタ」とよばれる特別な関数で、クラスからインスタンスを生成する際に呼ばれます。その際に new を使うのですが、その時には、コンストラクタで決められている引数を渡します。そうすると、その引数をつかってインスタンスが作られるというわけですね。Tamaクラスでは、必要となるx座標、y 座標、半径 r の3つの値を渡しています。
では、クラス化が出来た事でいっぱい増やす準備は整いました。では、じゃんじゃん増やして、弾幕を作っていきましょうか!
と、いいところまで来たのですが、ちょっと長くなってきたので、第4回に続きます!今回は、クラスの解説まで進みましたので、ちょっと難しかったかもしれません。そういう時は、サンプルのソースを、ちょっとづつ、変えて実行してみるといいと思います。変更して、どう変わるのか確認していくことは、プログラム上達の近道ですよ。すこしづつでもいいので、理解していきましょう。
今回は、クラスの説明に多くを割いたので、またまた、弾幕にはたどり着けませんでした。次回こそ!ではでは。
Related posts:
Post a Comment