Skip to content

第5回 Processing.js で初めてのゲームプログラミング

こんにちは、南治です。もう、早いもので第5回まできました。前回でようやく弾幕を張ることが出来たので、今回は予告どうり、当たり判定の組み込みを進めましょう。

当たり判定ルーチン(コリジョンとも言います)のアルゴリズムはいろんなゲームによって千差万別で、必ずこうしておけばいいという方法はなかなかありません。それぞれのゲームによって工夫して、より効率的にそれらしく当たり判定を考える必要があります。とはいえ、考えすぎて前に進めないので、まずはオーソドックスに弾と自機との距離を測る方法でいきましょう。

2つのポイントの距離を計算するためには、dist() 関数を使います。この関数を呼ぶと、2点間の距離が戻り値として返りますので、その距離が弾の半径(tr / 2) より小さければ当たっているとみなすことにしましょうか。このやり方だと弾の大きさしか考慮していない(自機の大きさが考えられていない)ため、正確ではないのですが、弾幕シューの場合、自機のコリジョンはかなり小さくするのが一般的なので、大丈夫な気がします。また、計算的に正しいことも重要ですが、ゲームの場合、プレイして楽しいこともとても大切なので、正確さよりも、実際のプレイ感覚が楽しい方に合わせてしまうこともよくあります。

ちなみに、図解すると今感じです。

弾と自機との当たり判定

そして、改造した該当箇所のソースはこのようになります。

class Tama {
  // ... 略
  boolean update() {
    tx += dx;
    ty += dy;
    stroke(255, 255, 0);
    noFill();
    ellipse(tx, ty, tr, tr);
    // area check
    if (ty > height || ty  width || tx < 0) {
        return false;
    }
    // hit check
    if (dist(tx, ty, ship.sx, ship.sy) < tr / 2)  // 自機との距離を計算 &当たり判定
      ship.hit();
   
    return true;
  }
}

弾の数だけ、自機との距離を計算し、当たり判定をしていかなくてはいけませんので、弾のupdate 関数に当たり判定を組み込みこんでいます。また、ボスにも当たり判定を入れる必要がありますね。ボスは自分の弾には当たらない(とおもう)ので、自機のレーザーとだけ当たり判定を行えば、OK でしょう。レーザーは縦一直線の形状なので、先程の点と点の距離を計算する dist() 関数は使えません。と、いっても難しく考える必要はなく、レーザーは一直線という特性を逆に活かして、自機のX座標(ship.sx)から出ているので、ボスのX座標(boss.bx)とだけ比較すればいいということになります。

class Ship {
  // ... 略
  void update(int x, int y) {
    sx = x;
    sy = y;
    stroke(255,255,255);
    fill(255 - hp, 0, 0);
    triangle(x, y - 7, x - 10, y + 7, x + 10, y + 7);
 
    if (mousePressed) {
      line(x, y, x, 0);
      if (abs(sx - boss.bx) < (boss.bw / 2)) // レーザーとボスとの当たり判定
        boss.hit();
    }
  }
}

レーザーの処理を行なっている箇所で、判定をしているのですが、そこで abs 関数を使っています。これは数値の絶対値を返す関数です。なぜ、このようにしているかというと、ボスと自機の位置関係によってはマイナスになります。計算結果が、プラスでもマイナスでもその大きさ(絶対値)だけが欲しいので、いったん、abs 関数を呼んでから、判定しているというわけですね。図にするとこんな感じです。

5-2-1

以上を踏まえた上で、動かしてみてみましょうか。Bossクラスと Ship クラスには、hp という変数を追加しました。ダメージを受けるとこの値を減らしていきます。また、ダメージの具合もしりたいので、このパラメーターをfill 関数の赤成分の引数として、渡すことで、ダメージを受けるたびに赤くなっていくようにしているところも、確認してみてください。

5-1
サンプルプログラム05-1

さて、当たり判定まで入りましたので、いよいよゲームクリア&ゲームオーバーのルーチンを入れていきましょう。ゲーム完成まで、あと一歩ですよ!

ゲームオーバーの処理を入れる準備として、画面に文字を出せるようにしたいともいます。Processing.js では何の準備もなしに text 関数を呼べば標準のフォントと大きさの文字が表示されるのですが、その場合のフォントは文字が小さく、あまり見やすくありません。なので、ちょっと大きめのフォントを出すために、手続きをします。PFont クラスを宣言し、createFont 関数で、使うフォント、大きさを生成し、textFont 関数で、text 関数が使用するフォントに指定するという流れになります。いささか面倒ですが、1度行うだけなので、setup 関数で実行するだけです。実際の使用箇所は、下記のような感じになりますよ。

PFont font;
void setup() {
  // ... 略
  font = createFont("FFScala", 24);
  textFont(font);
}

また、色を変えたい場合は、fill 関数を呼んで、色を指定することになります。

フォントの準備が出来たところで、ゲームクリア&ゲームオーバーの処理を入れていきます。ゲームクリアは、ボスのHP(boss.hp) が0になったとき、ゲームオーバーになるのは、自機のHP(ship.hp)が0になったときなので、それぞれの計算をしているところで、チェックを入れます。そして、じっさいに条件が成り立った場合、ゲーム全体の流れが、影響を受けますので、ゲームオーバーしているのかどうかのフラグ(gameover)を作り、その内容で、分岐するような処理を draw 関数に加えました。

void draw() {
  if (gameover) {  // game over
    textAlign(CENTER);
    if (ship.hp <= 0) {
      fill(255, 255, 255);  // blue
      text("YOU LOSE", width / 2, height / 2);
    } else {
      fill(255 * sin(frameCount), 255, 255 * cos(frameCount));  // red
      text("YOU WIN!", width / 2, height / 2);
    }
  } else {
    // 通常の処理
  }
}

で、ただ勝った、まけたでは微妙だったので、スコアの代わりに、ゲーム開始からの時間を右上に表示するようにしています。その際には、プログラムが動き始めてからの時間をミリセカンド単位で返してくれる millis 関数を使いました。詳しくは新設した print_time 関数(下記)を見てください。

// print time
void print_time() {
  float ft = (float)millis() / 1000;
 
  textAlign(RIGHT);
  text(nf(ft, 1, 2), width, 24);
}

というわけで、ゲームクリア処理も入り、スコアの代わりとしてクリアまでの時間も表示するようにしたプログラムが完成しました!ちょっと遊んでみましょう。

5-2
サンプルプログラム05-2

どうでしょうか・・・?
ゲームとしての最低限の体裁は整ってきたものの、いまひとつ、面白くありません!ぐぬぬ。
ちょっと残念ですが、ゲームのプログラムではこんなことは日常茶飯事です。というか、これからがゲームプログラムの本番だと言っても過言ではありません。これから、この体裁が整っただけのプログラムに改良を加えていって、「おもしろく」していくための改良が必要なのです。でも、ここからが、楽しいところなんですよ。

で、何か遊んでみると、いくつか問題がわかるとおもいます。大きな問題としては、ちょっと簡単すぎて、単調ですね。まずはそれらを調整していきましょうか。

ただ、ちょっと長くなってきたので、その改良プログラムについては次回の第6回におくりたいとおもいます。それまでの間に、みなさんもゼヒ、いろいろとおもしろくなるような改造を上記のソースに加えていってみてください。

では、また次回。いよいよ次回は最終回の予定ですよ!?

このエントリーをはてなブックマークに追加
はてなブックマーク - 第5回 Processing.js で初めてのゲームプログラミング
Post to Google Buzz
Share on GREE

Related posts:

  1. 第3回 Processing.js で初めてのゲームプログラミング
  2. 第4回 Processing.js で初めてのゲームプログラミング
  3. 第2回 Processing.js で初めてのゲームプログラミング
  4. 第1回 Processing.js で初めてのゲームプログラミング
  5. shi3z式ゲームプログラミング入門 #3 “ゲームらしく”する

Facebook comments:

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*