ASP.NET Core版 ボンバーマンのような対戦型ゲームをつくる(2)の続きです。

BomberHubクラスを定義する

以降は名前空間は省略して書きます。

フィールド変数

接続時と切断時の処理

接続時と切断時に行なわれる処理を示します。

接続されたらその旨をクライアントサイドに送信します。最初の1回だけTimer.ElapsedとGame.BombExplodedにイベントハンドラ追加の処理をおこないます。

ユーザーが接続したらクライアントサイドにデータを送信できるように、辞書 ClientProxyMapにClients.Callerを追加します。

それから後述しますが接続しているユーザーが0になった場合はサーバーへの負荷をへらすためタイマーを停止させます。そこで接続することで接続ユーザーが0から1になった場合はタイマーを起動させるとともに、NPC4体を初期の位置に戻し、破壊されたブロックを元に戻します。

切断時の処理を示します。

通信が切断されたら登録されているユーザーを辞書 ClientProxyMapから削除します。またプレイ中のユーザーが離脱したらPlayers辞書からも削除します。そして新しいNPCを生成してこれまでプレイをしていたユーザーにとっての初期位置を設定します。

また試合放棄?があった場合はゲームに参加しているユーザーだけでなくすべての観戦しているユーザーにこれを通知します。このときプレイヤー名にHTMLでエスケープすべき文字(とりあえず < と >)が含まれている可能性があるので置換しています。

ユーザーがゲームに参加したときの処理

観戦中のユーザーがゲームに参加したときの処理を示します。

この場合はNPCをひとつだけ除去して新しいプレイヤーを追加します。NPCが存在しない場合はクライアント側でゲームに参加するためのボタンが表示されないのですが、こちらでもチェックをしています。ゲームに参加できないときにこのメソッドを実行してもなにも起きません。

新しいプレイヤーが参戦した場合、すでに設置されている爆弾はすべてフィードから取り除きます。理由は爆弾の設置状況によっては新たに参加したプレイヤーがすでに爆弾に囲まれていたという状態を避けるためです。

またゲームに参加しているユーザーだけでなくすべての観戦しているユーザーにこれを通知します。ここでもエスケープ処理をおこないます。

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

タイマーのイベントが発生したときの処理を示します。

プレイヤーとNPC、爆弾、火花の状態を更新して当たり判定をおこないます。そしてクライアントサイドに描画処理に必要なデータを送信する準備をします。そのあとクライアントサイドにデータを送信するためのSendUpdateToClientメソッドを呼び出します。

更新時のデータを送信する

クライアントサイドにデータを送信するSendUpdateToClientメソッドを示します。

クライアントサイドへのデータ送信開始を知らせるReceiveStartUpdateを通知したあと、プレイヤー、爆弾、火花、破壊された壁の位置と状態を送信します。そして観戦しているユーザーの状態(参戦中か?参戦していないなら参戦は可能か?)を送信します。最後にすべてのデータを送信したことを知らせるReceiveEndUpdateを送信します。

当たり判定

当たり判定の処理を示します。ライバルが爆死したとき、それが自分が仕掛けた爆弾であれば1000点(990+10)、そうでない場合は10点を追加します。

さらにGame.SetDeadFireメソッドを呼び出して周囲にとぶ火花をセットします。そのあとPlayer.Deadメソッドを呼び出して再生またはゲームオーバーの処理を行なわせます。また爆死時に爆発音を鳴らすことができるようにクライアントサイドにReceivePlayerDeadを送信します。

爆弾が爆発した時の処理

爆弾が爆発したときの効果音を鳴らすために、Game.BombExplodedイベント発生時にはクライアントサイドにReceiveBombExplodedを送信します。そのための処理を示します。

ゲームオーバー時の処理

ゲームオーバーになったときの処理を示します。

ゲームオーバー時にはPlayers辞書からプレイヤーを取り除き、新しいNPCを生成します。そしてそのときに新しいNPCがどこに出現するかを伝えるためにPlayer.ResetNumberプロパティを取得して、これをつかって新しいNPCのResetメソッドの引数とします。

ゲームオーバーになったとき、30位以内に入っているのであればスコアランキングに登録します。そのための処理を示します。

まずスコア管理用のクラスを示します。前回の戦車対戦ゲームで定義したものとまったく同じですが、今度変更するかもしれないので別に定義します。

実際に必要であればスコアランキングに登録する処理を示します。カンマ区切りのテキストファイルにプレイヤー名とスコア、時刻を書き込みます。

まず既存のファイルがあるか確認し、ある場合は読み出してHiscoreオブジェクトのリストを作成します。そのあとゲームオーバーになったプレイヤーのHiscoreオブジェクトを追加してスコア順にソートします。そして上位30位を取り出します。最後にこれを文字列に変換してファイルに書き込みます。

キー操作への対応

最後にキー操作がされたときにサーバーサイドで処理できるようにする処理を示します。

ゲーム中にプレイヤー名を変更しても対応できるように、キー操作されるたびに対応したPlayerオブジェクトのNameプロパティに名前をセットしています。そのさいスコアランキングを保存するためのテキストファイルがカンマ区切りなので、プレイヤー名にカンマ(”,”)がある場合は他の文字に置き換えています。

Program.csに以下を追加しておきます。

Program.cs

スコアランキングの表示

スコアランキングを表示させるページをつくります。場所はゲームのページと同じ階層です。

/css/hiscore.cssの内容は クライアントサイドの処理 ASP.NET Coreで3Dっぽいカーレースをつくる(4)と同じです。

Pages\Bomber\hi-score.cshtml