JavaScriptで『スペースウォー!』(Spacewar!)をつくる(1)の続きです。前回定義したクラスをつかってゲームを完成させます。

ページが読み込まれたときの処理

イベントリスナを追加する処理を示します。

STARTボタンがクリックされたときにゲーム開始する処理、スマホ用の操作ボタンがクリックされたときの処理、ボリューム調整用のレンジスライダーを操作したときの処理、PCでキー操作されたときの処理ができるようにします。

showButtons関数は更新時にプレイ時でスマホ用操作ボタンの表示設定がONのときだけスマホ用の操作ボタンを表示させます。それ以外のときはボタンを非表示にします。

更新時の処理

更新時の処理を示します。プレイヤーの状態、火球の状態を更新して描画処理をおこないます。

プレイヤー(と火球)の状態を更新する処理を示します。

移動ボタンが押下されているときはその方向に回転させます。そのあとPlayer.Update関数を呼び出しますが、さらにそのあとpullToSun関数を呼び出します。これは太陽の重力を作用させる関数です。敵の動作と更新処理をしたあと、火球が存在する場合はこの更新処理をおこないます。最後に当たり判定をおこないます。

太陽の重力を作用させる処理を示します。

まずプレイヤーと太陽の距離から重力を計算します。重力は距離の2乗に反比例します。そのあとどの方向に作用させるかを求めます。これは太陽の座標とプレイヤーの座標をMath.atan2関数に渡せば求められます。あとは重力をプレイヤーの移動速度に加算します。

当たり判定と衝突後の処理

当たり判定の処理を示します。

片方がすでに死亡している場合は勝負がついているので当たり判定はしません。当たり判定をするときは太陽に衝突したか?弾丸が敵に命中したか?プレイヤー同士が衝突したか?を調べます。衝突時は死亡したプレイヤーの中心部を中心に爆発を発生させます。そのあと勝った場合、負けた場合、引き分けの処理をおこないます。

太陽との衝突判定

プレイヤーが太陽に衝突したかどうかを調べる処理を示します。(プレイヤーの中心と太陽の中心との距離)と太陽の半径を比較しているだけです。

弾丸との衝突判定

isBulletHit関数は第一引数で渡された弾丸の配列が第二引数で渡されたプレイヤーに命中しているかどうかを調べます。

プレイヤー同士が衝突判定

isCrashPlayers関数はプレイヤー同士が衝突したかどうかを調べます。playerInnerPointsで自機のパスを生成して、そのなかの敵機のplayerInnerPointsに含まれる点が存在するかを調べます。

勝敗決着後の処理

勝負がついたときの処理を示します。勝ったほうのスコアに1を加算します。3秒後に両プレイヤーの位置をリセットして次のゲームに移れるようにします。

描画処理

描画処理を示します。

背景を黒で塗りつぶし、プレイヤーと太陽、火球、スコアを描画します。

太陽を描画する処理を示します。

スコアを描画する処理を示します。

敵の思考ルーチン

敵の思考ルーチンを示します。

攻撃可能のときは攻撃を優先します。攻撃可能でない場合は太陽からの回避行動が必要かどうかを調べます。必要ないなら自機がいる方向に回頭、低速の場合は加速もおこないます。

自機の方向に回頭する

turnTowardsJiki関数は自機がいる方向に敵機を回頭させます。また太陽に対して安全な角度であれば加速します。また速度が0.5未満のときも加速させます。射撃が可能であれば射撃もおこないます。

canAttack関数は敵機から自機を射撃可能かを調べます。自機の方向と敵機の現在の方向のズレが左右60度以内で距離が280未満の場合は射撃可能と判断します。

太陽に対して安全な角度か?

敵機が太陽に対して安全な角度であるかどうかを調べます。ここでは太陽を背にする角度から左右120度=太陽に対して左右60度以上のズレがあれば安全と判断します。