はじめに
前回までの記事で、画面にキャラクターを出すところまではかけたので、今回は敵を作ります。
シューティングゲームにおいて、敵を作るという事は、どのように敵を動かすかだと思います。さらに単純化すると、**画面にどのように線を引くか、**となります。
Phaserのライン計算機能を使う
オフィシャルチュートリアルに、曲線に関する機能の紹介があります。
Phaserには、任意の二次元座標の配列と、それを結ぶアルゴリズム、スプライトがその線上の何%の位置にいるのか、を指定する事で、その時点での座標を算出する機能が備わっています。アルゴリズムは直線、スプライン、ベジエに対応しています。
結果のキャッシュ
この機能は、座標の集合とスプライトの位置を指定するたびに座標を計算して返すため、ややCPUを食います。このため、座標の集合が動的に変化しないのであれば、計算結果をキャッシュしておく機構があった方がよいです。連続曲線の座標を配列に持つ訳です。
座標の集合が動的に変わる例としては、自機の座標にあわせて誘導する敵が挙げられます。
計算結果をキャッシュしておく都合上、敵キャラの移動パターンは予め数種類用意しておき、それらの組み合わせで複雑な動きをさせた方がよいと思います。
おまけ:僕の実装例
フレームレートが低いですが、こんな感じで、曲線を描いてスプライトを動かせます。
この例では、同じモーション(計算結果のキャッシュ)を3つのスプライトで共有しています。
各々、初期位置とスピードが違うだけですが、わりとそれっぽく見える物ですね。
モーションデータは、点の座標を4個ほど入力し、それを全てつなぐ曲線を計算し、計算結果の座標を1200個の配列に保持しています。
各スプライトが、毎フレーム、1200個の配列の先頭から座標を取得し、自分の開始地点などを加味して現在座標を算出してそこにレンダリングされます。スピードが速いスプライトは、配列のインデックスを進める量の多さで実現しています。
あとでギッハブのURLもはっておきます。
おまけ2:あたり判定の罠
Phaserには、Spriteが画面外へ出たらkill()を実行する、outofBoundsKillというプロパティが生えています。
結構便利なように見えますが、これを有効にした場合、そのSpriteは毎フレーム、スプライト全体が画面外に出ていないかチェックされます。
簡単に言うと、スプライトが四角形だった場合に、その4つの頂点の座標全てが、画面外に出ていないか毎フレームチェックしているという事です。計算量4倍です。
多くの場合において、そこまでの精度は必要ない事が多いです。スプライトの座標が、画面外へ充分離れたらkill()を呼ぶ、というのを各Spriteのupdate()内でやった方がマシだと思います。これなら、どんな多角形であろうと、計算は最大4回ですみます。
(Spriteのサイズと画面のサイズが予め定まっている場合)
実際ドキュメントにも
This is a relatively expensive operation, especially if enabled on hundreds of Game Objects. So enable it only if you know it's required, or you have tested performance and find it acceptable.
(この処理は、特に数百のスプライトに適用すると、わりと高負荷なので、必要な時にonにするか、テストしつつ処理量を見極めて使ってね)
と書いてあります。利用する場合はご注意ください。