前回は通路の描画とプレイヤーの移動と描画処理を実装したので、今回は敵の動作と描画の処理の実装を考えます。

Enemyクラス

Enemyクラスを作成してそのなかで移動に関する処理をおこないます。

初期化

まずコンストラクタを示します。

コンストラクタの引数はXYの初期座標と識別IDです。InitXとInitYは初期座標、XとYは現在の座標です。MaxNumberOfTimesToMoveはこの回数分のUpdate関数が呼び出されないと巣のなかから外には出てこない回数です。最初はNumberOfTimesToMoveはMaxNumberOfTimesToMoveと同じで、Update関数が呼び出されるたびに1少なくなります。そして0になると巣の外にでてプレイヤーを追跡しはじめます。

敵の初期化をおこないます。プレイヤーによって撃退されたときや、ゲームスタート時やステージクリア時やミス時に敵を初期位置に戻すときに実行されます。

InitXとInitYは通路上における敵の初期座標です。巣のなかにいるときはそのように見せるためにそれよりもY座標を大きな値を設定してそのよに見せかけます。

移動方向を取得する

GetDirect関数は敵が次に移動する方向を決めるためのものです。通路が立体交差になっているので南北、東西の橋と通路の交差点について南北にしか通行できない、東西にしか通行できない場合にわけてそのなかから最短経路を求めています。

立体交差が2箇所あるので全部で4とおり調べないといけません。もっと効率的なやり方があるかもしれないのですが、空を飛ぶために身体を軽量化し、その結果脳みそも小さくなってしまった鳩にはこんな方法しか思いつきません。もっと効率よく計算する方法があるならこっそり教えてください。

GetDirect関数内でGetDirect2関数が呼び出されていますが、その部分を示します。

引数は南北にかかっている橋を通るのか否か、東西にかかっている橋を通るのか否かです。あとはダイクストラ法で最短経路を求めています。現在位置からプレイヤーのいる座標にたどり着くために最初に移動すべき方向がその敵が移動すべき方向です。このような方法で敵が次に移動する方向を求めています。

移動させる

Move関数は実際に敵が別の座標に移動するための関数です。

まず敵がいる座標が通路ではない場合(map[this.Y][this.X] == POSITION.POSITION_NONEの場合)、巣のなかにいると判断します。敵が巣のなかにいるときはNumberOfTimesToMoveを減算します。すでに0になっているときは上方向に移動させます。

すでに敵が巣の外に出ている場合(map[this.Y][this.X] != POSITION.POSITION_NONEの場合)は敵を移動させます。敵が方向転換できるのは角や丁字路、十字路にいる場合です。敵がいる座標の上下左右がPOSITION.POSITION_NONEであるかどうかで上下左右にそれぞれ移動できるかはわかります。

角や丁字路、十字路にいる場合は前述のGetDirect関数で方向転換の処理をおこないます。取得された新しい進行方向をメンバ変数EnemyDirectに格納しておきます。

いまはまだ実装していませんがプレイヤーがローラーをつかって敵に反撃しようとしているかもしれません。実際に自分でプレイしてみましたがある特定のパターンに入ると永久に点数稼ぎができてしまうため、敵を倒し続けた場合、ローラーから逃げる動作を追加します。関数内のif文で使われているaddPointCrashEnemyはグローバル変数です。

敵を移動させる方向が決まったらに現在の座標から移動させる処理をおこないますが、このとき通路の端にいる場合は反対側にワープさせる処理をおこないます。

クラスの外での処理

ここからはクラスの外での処理になります。

初期化の処理

まず初期化の処理をおこないます。Enemyオブジェクトを格納する配列を作成します。InitEnemies関数は配列の中身を空にして新しく作成したふたつのEnemyオブジェクトを格納します。そしてEnemyクラスのメンバ関数Resetを呼び出して巣のなかに敵を移動させます。

移動処理

MoveEnemies関数はenemiesに格納されているEnemyオブジェクトを移動させます。

描画処理

DrawEnemy関数はEnemyオブジェクトを描画します。IDを調べて適切なイメージで描画処理をおこないます。

DrawEnemiesはまとめて描画処理をおこなうためのものです。

ReDrawEnemiesIfNeedは橋を描画することで本当は描画されなければならない敵が隠れてしまったときに再描画をするためのものです。

既存の関数の修正

描画対象に敵を追加したので、必要に応じて既存の関数を修正します。

Update関数を修正します。MoveEnemies関数を追加します。

敵を描画する処理を追加しないといけないのでDraw関数も修正します。

ページが読み込まれたときに敵を初期化する処理を追加します。