ASP.NET Core版 タイピングゲームをつくります。今回はサーバーサイドの処理を実装します。

タイピングゲームは他にもありますが、入力するのは半角のアルファベットになっているものが多数です。これだと「ふ」が「hu」か「fu」かの違いでじつはひらがな入力をするのであれば同じなのに誤答扱いになってしまいます。そこでプレイヤーはローマ字入力でもカナ入力でも遊べるようなものとして作ります。

それからこのページの説明は NET 6.0をエックスサーバーにインストールするで示している手順が完了していることを前提としています。

ではさっそく作成することにします。名前空間はTypingとします。C#で書かれたソースはPages\Typingに置きます。

まずゲームに関する処理をおこなうTypingGameクラスを定義します。

TypingGameクラスの定義

以降は名前空間を省略して以下のように書きます。

初期化

TypingGameクラスのコンストラクタを示します。

引数はAspNetCore.SignalRでサーバーサイドに接続したときに付与されるIDです。これをConnectionIdプロパティにセットしています。ConnectionIdプロパティは後述します。またタイマーの初期化もしています。イベントハンドラTimer_Elapsedについては後述します。

各プロパティ

ゲーム開始時の処理

ゲーム開始のときに呼び出されるGameStartメソッドをしめします。

ここでは _isGamingをtrueにしてゲームが現在おこなわれていることがわかるようにします。ゲーム開始時はミスによってゲームが中断されている状態ではないので _isStopingはfalseにします。Lifeは最大値に、Scoreは0にします。1問あたりの制限時間を示すTimeLimitMaxプロパティはTIME_LIMIT_MAXにします。

そのあと新しい問題を作成します。後述するCreateQuestionsメソッドでお題の文字列の配列をフィールド変数 _questionsに格納します。そして _indexを0に戻し現在のお題が格納されているQuestionプロパティには _questions[0]を格納します。これを後述するSendQuestionメソッドでクライアントサイドに送信します。

問題を生成するためのCreateQuestionsメソッドを示します。テキストファイルを読み取り、お題を文字数が少ない順にわけます。そして文字数が同じもの同士の順番をランダムに変更します。この処理で得られた文字列の配列をコンストラクタ内でフィールド変数 _questionsに格納しています。

新しいお題の送信

新しいお題を取得してSendQuestionEventイベントを発生させてこれをクライアントサイドに送信します。お題を解くための残り時間を計算できるように出題した時刻をフィールド変数 _dateTimeに格納しています。

送信された文字列の正誤判定

CheckAnswerメソッドはクライアントサイドから送られてきたお題の答えが正しいかどうかを判定します。正解ならCorrectAnswerEventイベントを送信し、不正解ならIncorrectAnswerEventイベントを送信します。

正解の場合は残り時間から加算する点数を計算(最低10点~最大100点)してScoreプロパティの値を増加させます。そして制限時間を0.3秒短くします。そして次のお題を出題します。配列_questionsの最後の要素までいっているのであれば最初の要素に戻します。

不正解の場合はIncorrectAnswerEventイベントを送信するだけでなにもしません。

更新処理

Timer.Elapsedイベントが発生したらUpdateメソッドを呼び出し、だんだん少なくなっている解答を提出するまでの残り時間をクライアントサイドに送信します。

ゲーム開始前とゲームオーバー後は更新処理はおこないません。

ゲーム中は現在時刻と _dateTimeの差から消費時間を算出し、それとTimeLimitMaxとの差から残り時間を計算します。そしてUpdateEventイベントを送信します。こうすることでクライアントサイドには残り時間を送信することができます。

もし残り時間が0以下であればミス時の処理がおこなわれます。そのときはLifeがデクリメントされ、UpdateEventイベントとMissEventイベントが送信されます。その後、3秒間ゲームの進行が停止します。そのあいだ _isStopingがtrueとなります。

_isStopingがtrueである場合はTimeLimitが0以下でもミスの処理が重ねておこなわれないようにif文で制御しています。3秒間ゲームの進行が開始されますが、そのときにLifeが0になっているとゲームオーバーの処理がおこなわれます。Lifeが1以上のときは新しいお題でゲームが再開されます。

ユーザー離脱時の処理

ゲームオーバーになる前にユーザーが離脱してした場合は更新処理をする必要はないのでUpdateメソッドが呼び出されないようにします。またイベントハンドラ Timer_Elapsedも外してしまいます。

ユーザーが全員離脱してしまった場合はサーバーに負荷をかけないようにタイマーを停止させます。その処理を示します。