挟み撃ちのアルゴリズムを研究するために絶対に攻略できないクソゲーをつくります。

まずは普通のパックマンをつくります。

HTML部分

HTML部分を示します。

style.css

グローバル変数と定数

グローバル変数と定数を示します。

index.js

二次元配列 map

通路と餌の位置、プレイヤーと敵の初期位置などをpngファイルとしてまとめたものがこれです。

座標が1ピクセルでは見づらいので見やすくするために太く描画したものがこれです。

この各ピクセルを二次元配列に変換したのがこれです。

この二次元配列 mapを解析して必要な座標を求めます。

Foodクラスの定義

フィールドに存在する餌を描画するためにFoodクラスとPowerFoodクラスを定義します。IsDead == trueなら存在しないのでフィールドから取り除きます。

Playerクラスの定義

プレイヤーを移動させ描画するためにPlayerクラスを定義します。

初期化

コンストラクタと初期化の処理を示します。

移動させる処理

プレイヤーを移動させる処理を示します。CurDirectをみてプレイヤーの座標を変更します。そのまえに次の移動方向が移動可能であればCurDirectにセットします。NextDirectの値はユーザーのキー操作で変更されます。

描画処理

描画処理を示します。

Enemyクラスの定義

敵を移動させ描画するためにEnemyクラスを定義します。

初期化

コンストラクタと初期化の処理を示します。

移動方向に関する処理

CanChangeDirect関数は敵が引数の方向に移動できるかを調べます。

GetNextDirects関数は敵が移動できる方向の配列を返します。配列に格納される順番は先頭が現在の移動方向(ただし移動可能な場合)、末尾が現在の移動方向と逆方向(同前)になります。これでとりあえず先頭の要素を取得すれば敵を移動させ続けることが可能です。また敵をUターンさせたくない場合は、末尾を捨てればよいことになります。

GetReverseDirect関数は敵の現在の移動方向と反対の方向を返します。

Reverse関数は敵を移動方向を反転させます。反転できない場合はランダムで移動方向を決めます。

ChageIjikeMode関数は敵をイジケ状態に変化させます。そして元来た道を逆走させます。

GetPathToHome関数は撃退され巣に戻る敵が通る座標の配列を返します。

幅優先探索でeHomeFrontまでの最短経路を取得し、そこにいたる座標の配列を取得します。

更新処理

更新処理を示します。

PositionsToHomeに要素が格納されている場合は撃退されて巣に戻っているときなのでPositionsToHomeの先頭の要素を取り出して、これを敵の現在位置とします。ただし移動速度を通常移動より速くしたいので要素が2つ以上あるときはshift関数を2回呼び出しています。

配列PositionsToHomeが空でも死亡フラグが立っている場合は巣の中心部へ降下させます。中心部まで降下したら死亡フラグをクリアします。イジケ状態から回復させてStatusを’out’にします。これによって敵はすぐに巣の中心部から外に出てきます。

IjikeTimeが0より大きい場合は移動速度を半分にするためIjikeTimeが偶数のときはなにもしません。

Status == ‘wait’のときは巣のなかで上下に移動させます。Y が eHomeMinYまたはeHomeMaxYと同じなら上下の方向転換をします。Y == eHomeCY のときは WaitTime をデクリントします。WaitTime == 0になったらStatusを’out’に変更します。Status == ‘out’のときはまっすぐ上昇すれば巣から出られるときは上昇させ、そうでないときはX座標をeHomeFrontXに向けて1増減させます。

Status == ”のときは完全に巣から出た状態なのでDirectの方向へ現在位置を移動させます。

描画処理

敵を描画する処理を示します。

描画時に使用するイメージですが、イジケ状態で3秒以内に元に戻る状態ではijikeImages[0]とijikeImages[1]を交互に使います。それ以外の場合はijikeImages[0]を使います。イジケ状態ではない場合はenemyImages[this.Type]を使います。

今回はクラスの定義だけになりました。まずは普通のパックマンをつくらないといけないのですが、もう少し時間がかかりそうです。なかなかクソゲーの核心部分にたどりつけませんが、生温かくお見守りください。