Slither.io (スリザリオ)のようなオンラインゲームを作りたい(5)の続きです。今回はクライアントサイドの処理を実装します。

cshtmlファイルとCSSについて

Index.cshtmlとCSSを示します。

Index.cshtml

style.css

グローバル変数と定数

グローバル変数と定数は以下のとおりです。

app.js

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

ページが読み込まれたときは以下の処理がおこなわれます。

canvasサイズの設定
テキストボックスに以前に使ったプレイヤー名があるならこれを設定する
描画に使うイメージの初期化
イベントハンドラの追加
ボリュームコントローラーの初期化
BGMをエンドレスで再生できるようにする
ASP.NET SignalRでサーバーに接続する

これは画像ファイルを読み込んで描画用のイメージを配列に格納する処理です。

イベントリスナを追加する処理を示します。ここではスタートボタンを押下したとき、PCのキー操作、操作用のボタンを操作したときの処理を追加しています。

レンジスライダーを操作することでボリュームを操作できるようにする処理を示します。

接続成功時の処理

サーバーに接続できた場合、ASP.NET SignalRで使われる一意の接続IDとフィールドの半径が送信されるので、これをグローバル変数に保存しておきます。

ゲーム開始の処理

ゲーム開始時におこなわれる処理を示します。テキストボックスに入力されている文字列をローカルストレージに保存するとともにサーバーサイドのGameStartメソッドを呼び出します。

上記の処理が成功したらサーバーサイドからSendToClientGameStartSuccessfulイベントが送信されます。このイベントを受信したときは以下のような処理がおこなわれます。

Circleオブジェクトが格納されている辞書mapCirclesのクリア
isGameoveredフラグのクリア
矢印キーを押下したときのデフォルトの動作を抑止するisPreventDefaultフラグのセット
ゲーム開始ボタンとプレーヤー名入力用のテキストボックスの非表示
ディスプレイ幅が620ピクセル以下のときは自機操作用のボタンの表示
BGMの再生開始

各イベント時の処理

SendToClientUpdateFieldStatusとともにプレイヤーやNPC、餌の総数が送られてくるので、これをゲーム画面の下部に表示させます。

SendToClientUpdateMyStatusとともに自機の状態が送られてくるので、これをグローバル変数に格納しておきます。これはプレイヤーを描画するときに必要な情報です。

他のプレイヤーを倒したときはSendToClientKillPlayerイベントが送信されるので効果音を鳴らします。

なんらかの原因で通信が切れてしまったときは通信が切断された旨を表示します。

描画処理

描画にかんする処理を示します。

まずcanvas上に大量の円を描画するためCircleクラスを定義します。

サーバーサイドからSendToClientUpdateCirclesイベントが送信されてきたらcanvasに新しく追加する円と消去する円を調べてmapCircles辞書内に格納されているCiecleオブジェクトを更新します。

removeCirclesTextは削除するCiecleオブジェクトのIDがカンマ区切りで格納されています。addCirclesTextは追加するCiecleオブジェクトの情報が改行文字とタブ文字区切りで格納されています。これを配列に分解してmapCircles辞書を更新します。

また円が追加されることによってそのCiecleオブジェクトが各プレイヤーの先頭から何番目なのかが変わります。なので削除すべきオブジェクトを削除したらそのあとでCircle.NumberFromHeadをインクリメントしています。

辞書の内容で描画処理をおこなう処理をしめします。

canvas全体を黒で塗りつぶす
自機を中央に描画するために全体の座標をどれだけずらすのかを計算する
フィールドを表す円を描画する
circleオブジェクトを辞書から取り出して生成順にソートする
circleオブジェクトが餌なのかプレイヤーの頭なのかそれ以外の部分なのかを調べて描画する
ただし頭は最後にまとめて描画し、近くにプレイヤー名と体長などの情報も表示する

circleオブジェクトを生成順にソートするのは餌でプレイヤーが上書きされないようにするためです。

他のプレイヤーの状態とレーダーの描画

他のプレイヤーがどこにいるのかがわかるように座標と体長を表示させます。また左下部分にレーダーを描画して視覚的にわかるようにします。

まずプレイヤーの情報を操作するためにPlayerクラスを定義します。

SendToClientUpdatePlayersStatusイベントとともに文字列が送られてくるのでここからPlayerオブジェクトの配列を生成して体長が長い順にソートします。順位をゲーム画面下部に表示し、各プレイヤーの位置をレーダー上に描画します。

ゲームオーバー時の処理

ゲームオーバー時にはSendToClientGameOveredが送信されます。

このときは以下の処理をおこないます。

操作用ボタンの非表示
サーバーサイドへの旋回、ダッシュの取り消しを送信する
操作用ボタンが押下されているかどうかを示すフラグのクリア
BGMの停止
ミスを示す効果音の再生

またその2秒後には以下の処理もおこないます。

ゲームに再挑戦するためのスタートボタンの再表示
ゲームオーバーを示す効果音の再生
矢印キーのデフォルトの動作の抑止の取り消し

ランキングページの表示

最後にランキングページを表示させる処理を示します。

Gameクラスの定義 Slither.ioもどきを作る(4)で定義したScoreRankingクラスのLoadメソッドでHiscoreのリストを取得して長さとKill数でソートした結果をそれぞれ表示させるだけです。

hi-score.cshtml

ranking-style.css