前回 ASP.NET Coreで3Dっぽいカーレースをつくる(3)の続きです。今回はクライアントサイドの処理を解説します。

まず車とコース、コースの境界にある円錐状のものを描画する処理とその座標ですが、これはコースを描画する TypeScript/JavaScriptでもつくる3Dカーレースゲーム(3)で作成したものをそのまま使います。

以下のリンクからダウンロードできます。

create-car-functions.js
get-course-border.js
get-course-inside.js

このなかで車の描画に必要なCreateOrangeCar1関数、CreateBlueCar1関数、CreateBlueCar2関数、CreateRedCar1関数、CreateRedCar2関数、CreateYellowCar1関数、コースの内側を黒く塗りつぶすために必要なGetCourseInside関数、コースの境界線に円錐状のものを設置するためのGetCourseBorder1関数とGetCourseBorder2関数が定義されています。

cshtmlファイル

ページ数が増えてきてPagesフォルダ内のファイルが増えてきたのでCarRace3dというフォルダをつくってそこで公開します。そのためJavaScriptやmp3ファイルを指定するときに少し注意が必要です。

Pages\CarRace3d\game.cshtml

JavaScript グローバル変数

JavaScriptのファイルを読み込んでいますが、上の3つはすでに紹介したとおりなのでapp.jsについて解説します。

car-race-3d/app.js

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

ページが読み込まれたときの処理を示します。

car-race-3d/app.js

上記関数内で呼び出されている関数を示します。

BGMを鳴らすかどうかを選択するチェックボックスの状態が変化したときにBGMの再生と停止処理をおこないます。

BGMの再生を再生します。102秒で1回の再生が終わるので102秒間隔で繰り返し再生をおこないます。

BGMの再生を停止します。

ボリュームをセットします。

ユーザーがわかりやすいように操作方法を表示します。

ゲーム開始前は自車を回転させて表示させます。

ライバル車を生成します。スタートボタンを押すまでは表示させないのでY座標を負数にしています。

コースをsceneに追加

ゲームが開始されたらコースをsceneに追加します。

以下はInitGame関数内で呼び出されている関数です。

コースの左側と左側に円錐状のオブジェクトをつくります。

コースの内部に黒い板を敷き詰めます。

スタート地点がどこかわかるように赤いラインを表示させます。

更新処理

ゲーム中の更新処理を示します。

Update関数のなかで呼び出されている関数を示します。

一定の速度を出して曲がろうとすると効果音を再生します。

カメラに自車の後ろを追わせます。

前方に存在するライバルのプレイヤー名を表示させます。

ゲームオーバーの時はその旨を表示させます。

SignalRの接続と受信時の処理

SignalRの接続とデータを受信したときの処理を示します。

接続と切断

connectionID == ”でSキーが押されたときはSignalRで接続し、サーバサイドに対してゲームスタートの処理をする旨を送信します。そのための処理を示します。接続に失敗したときはその旨を表示させます。

サーバーサイドから接続に成功した通知を受信したときの処理を示します。成功したらconnectionIDをグローバル変数に保存しておきます。

切断された通知は受信したときの処理を示します。connectionIDを空文字列とし、切断を表示します。

ゲーム開始成功時の処理

サーバサイドからゲームが開始された通知を受信した場合、sceneにコースや車が追加されていない場合はInitGame関数を呼び出して追加の処理をおこないます。そしてチェックボックスにチェックがある場合はBGMを再生します。

キー操作への対応

キーがおされているときの処理を示します。まだ接続されていない場合、ゲームオーバー後に通信が切れている場合は前述のConnectAndGameStart関数を呼び出し、接続とゲームスタートの処理をおこなおうとします。

すでに接続されている場合は押されたキーとプレイヤー名をサーバサイドに送信します。

キーが離されたときの処理を示します。connectionIDが空文字列でない場合はサーバサイドに離されたキーを送信します。

更新処理

サーバーサイドから更新処理をおこなう旨を受信したときの処理を示します。

更新するのは自車だけでなくライバル車全体の座標、回転状態、プレイヤー名です。そこでライバル車の状態を一時保存するための配列を用意します。

ReceiveStartUpdateを受信したら配列を空にします。そしてReceiveUpdateを受信したら、それが自車のものかライバル車のものかを送られてきたconnectionIDとグローバル変数に保存したものとを比較して調べます。そして自車なら自車用の一時変数、ライバル車であればライバル車用の一時変数に保存します。ReceiveEndUpdateを受信したら前述のUpdate関数を呼び出して更新処理をおこないます。

走行距離や時速などのプレイヤーの状態を受信したらこれをcanvas上部に表示させます。

クラッシュ時の処理

サーバーサイドでイベントが通知されたらそれに対応した処理をおこないます。

クラッシュしたらクラッシュ時の効果音を鳴らします。

復帰時の処理

クラッシュから復帰したらisAliveフラグをセットして再びカメラが自車を追うようにします。

ReceiveGameOveredを受信したらゲームオーバーになったということなので、BGMを停止してcanvasにその旨を表示させます。このあと前述のとおりサーバーサイドで通信を切断する処理がおこなわれます。

ゲームオーバー時の処理

ゲーム参加を拒否されたときの処理

すでにプレイできる最高人数に達しているにもかかわらずゲームを開始しようとしたときはReceiveDenyNewPlayerを受信することになります。この場合はdeny-new-playerページにリダイレクトします。

deny-new-playerページの内容ですが、あまり作り込むようなものではないので以下のような簡単なものにしています。

Pages\CarRace3d\deny-new-player.cshtml

スコアランキングの表示

スコアランキングのページは以下のようになっています。

Pages\CarRace3d\hi-score.cshtml

CSSファイルですが、以下のようになっています。

wwwroot\css\hiscore.css