前回 ASP.NET Coreで3Dっぽいカーレースをつくる(2)の続きです。

CarRace3dHubクラスの定義する

インデントが深くなるので以降、この記事のなかでは

と書きます。

フィールド変数

まずフィールド変数を示します。ほとんどが静的なものです。

接続成功時の処理

接続に成功したときの処理を示します。

接続成功に成功したことをクライアントサイドに通知します。また最初の接続がおこなわれた場合は、NPCを生成します。プレイできる人数の上限は7人なので、それ以外はNPC(non player character)です。そこで6つのPlayerオブジェクトをNPCとして生成します。タイマーのイベントは1秒間に24回発生させます。

そのあと各プレイヤーにサーバサイドから送信するときにIClientProxyが必要になるので辞書に格納しています。またサーバー側から通信を切断する必要が生じる場合もあるのでHubCallerContextも辞書に格納しています。またContext.ConnectionIdからPlayerオブジェクトを取得できるようにこれも辞書に格納しています。

このとき接続されているユーザーが1の場合は停止しているタイマーをスタートさせます。

それから「サーバー側から通信を切断する必要が生じる場合」ですが、大人数でプレイしようとするとサーバーに負荷がかかりすぎるのとクライアントサイドでも描画処理に時間がかかりカクカクしてしまうのでプレイできる人数は7人に限定しています。8人目がアクセスしようとすると別のページにリダイレクトさせて通信を切断する処理をおこないます。

二人目以降がアクセスするときはすでにプレイしている人とNPCが6つあるのですが、このような場合はNPCをひとつ取り除き、そこへ新しいPlayerオブジェクトを追加します。Playerオブジェクトを追加したらイベントハンドラを追加して、クラッシュ、回復、ゲームオーバー時のイベントに対応できるようにします。そしてクライアントサイドにゲームが開始されたことを通知します。

イベントハンドラの定義

クラッシュとそこから回復したときのイベントハンドラを示します。クライアントサイドにその旨を送信します。

ゲームオーバー時のイベントハンドラを示します。ゲームオーバーになったらそれをクライアントサイドに送信するのですが、他にもおこなわれる処理があります。

ゲームオーバーになったときはゲームオーバーの通知だけでなく、canvas上部に表示させる文字列も送信します。ゲームオーバーになるとプレイできる人数に上限があるので通信を切断します。通信がきれてしまうので「残機 0」の表示がされなくなるのでcanvas上部に表示させる文字列も送信する必要があるのです。

またPlayers辞書から格納されているPlayerオブジェクトを取り除き、これをNPCsリストに追加します。このときにPlayerオブジェクトのプロパティをNPC用に変更できるように、前述のPlayer.ToNPCメソッドを呼び出します。

通信を切断する処理

ゲームオーバーになったときに通信を切断するための処理を示します。HubCallerContexts辞書を検索してみつかったHubCallerContextをAbortします。

切断されたときにおこなわれる処理

切断されたときに呼び出されるOnDisconnectedAsyncメソッドについて示します。辞書から必要なくなったデータを削除しています。

キー操作に対応する処理

ユーザーによってキーがおされたときと離されたときの処理を示します。Playerクラス内のフラグをセットしたりクリアします。またキーが押されたときはユーザーが設定しているプレイヤー名もPlayer.Nameプロパティにセットします。ゲームの途中でユーザーが再設定する可能性もあるので、キーが押されるたびにPlayer.Nameプロパティをセットしなおします。

更新を通知する処理

車の状態をクライアントサイドに通知するための処理を示します。通知するのはXYZ座標、XYZ方向の回転、速度、各プレイヤーの名前です。

タイマーイベント発生時の処理

タイマーのイベント発生時の処理を示します。プレイヤーとNPCをまとめてGame.OnTimerメソッドに渡します。すると移動処理がおこなわれます。

当たり判定

当たり判定の処理を示します。このときクラッシュしてスピンしている車やクラッシュから回復して無敵状態(5秒)にある車との当たり判定はおこないません。当たったようにみえてもすり抜けてしまいます。

スコアランキング登録の処理

最後にゲームオーバー時にスコアランキングに登録する処理を示します。

まずスコアを管理するクラスを定義します。名前空間がZero.Pagesになっていますが、これはプロジェクト名がZeroになっているからです。

以下の処理はプレイヤー名とスコアを30位以内であれば登録するための処理です。