Skribbl.io のようなリアルタイム マルチプレイヤー ゲームの作成は、Web 開発のさまざまな側面を組み合わせたエキサイティングな挑戦です。この記事では、リアルタイム クローンを構築する際の実装と考え方について、ラウンド ベースでタイマー システムのゲームをどのように処理できるかについて説明します
プロジェクトのソース コードをチェックアウトしたい場合は、ここ Github で見つけることができます
技術スタック
詳細に入る前に、このプロジェクトで使用される技術スタックを簡単に見てみましょう:
- Node.js: バックエンドサーバー用。
- Socket.IO: リアルタイム通信用。
- Redis: 効率的なデータ処理用。
- Vite: React を使用した迅速な開発用。
- TypeScript: フロントエンドとバックエンドの両方でのタイプ セーフティのため。
- React: ユーザー インターフェイスの構築用。
- Docker: アプリケーションのコンテナ化用。
バックエンドのセットアップ
バックエンドは、リアルタイム インタラクションの処理に最適な Node.js と Socket.IO を利用しています。主なコンポーネントの概要を次に示します:
1. リアルタイム通信のための WebSocket
Socket.IO により、サーバーとクライアント間のシームレスな通信が可能になります。プレイヤーのルームへの参加、ゲームの開始、描画データの送信などのイベントを処理するためにこれを使用します。
2. ルームシステム
各ゲームは、ルーム ID によって識別される固有のルームでホストされます。プレイヤーはこの ID を使用してルームに参加し、同じルーム内の他のプレイヤーと対話します。システムはプレーヤーの接続と切断も処理します。
しかし、ここで問題が発生します。サーバーがクラッシュした場合、ゲーム内にあったデータをサーバーが保持しているとどのように保証できるのでしょうか
ここでは、高速でサーバーとは別のデータベースを使用します
Redis は、このようなタイプのユースケースに最適です。インメモリ データベースなので高速で、別のサーバーで個別に実行できます
これについては、後の投稿で詳しく説明します。
3. イベント処理
サーバーはさまざまなイベントをリッスンし、発行します。
-
クライアント イベント: connect、disconnecting、joinRoom、leaveRoom、startGame、draw、guess、changeSettings、wordSelect
-
サーバー イベント: JoinRoom、playerJoined、playerLeft、gameStarted、gameEnded、drawData、guessed、turnEnded、chooseWord、wordChosen、settingsChanged、guessFail
フロントエンドの開発
フロントエンドには、開発エクスペリエンスをスムーズにするために、TypeScript と Vite で React を使用しました。
1. UIの構築
ユーザー インターフェイスには、ゲーム設定の描画、推測、管理のためのコンポーネントが含まれています。 React のコンポーネントベースのアーキテクチャにより、動的で応答性の高い UI を簡単に作成できました。
2. ゲーム状態の処理
フロントエンドは、プレイヤーのスコア、現在のターン、描画データなどのゲーム状態を管理します。 TypeScript は、データ構造が明確に定義され、エラーがないことを保証します。
3. リアルタイム更新
Socket.IO を使用すると、フロントエンドはサーバー イベントに基づいてリアルタイムで更新されます。たとえば、プレイヤーが描画すると、描画データがルーム内のすべてのクライアントに送信されます。
ゲーム状態管理
Skribbl.io のようなリアルタイム マルチプレイヤー ゲームでスムーズで楽しいエクスペリエンスを確保するには、効果的なゲーム状態管理が不可欠です。ここでは、ゲーム状態のさまざまな側面がどのように管理されるかを詳しく見ていきます:
プレイヤーの参加と退出
ルームへのプレイヤーの参加と退出を管理するには、いくつかの重要な手順が必要です:
-
参加中:
-
イベントの送信: プレーヤーがルームに参加したい場合、ルーム ID を含む joinRoom イベントをサーバーに送信します。
-
検証: サーバーはルーム ID を検証し、ルームが存在するかどうかを確認します。
-
プレーヤーの追加: 有効な場合、プレーヤーはルームのプレーヤー リストに追加されます。その後、サーバーはゲームの状態を更新し、ルーム内のすべてのクライアントに playerJoined イベントを発行して、新しいプレイヤーの到着を通知します。
-
UI の更新: フロントエンドでは、新しいプレーヤーの存在がルームのプレーヤー リストに反映され、全員が最新のプレーヤー名簿を確認できるようになります。
-
出発:
-
イベント発行: プレーヤーが退出することを決定すると、サーバーに LeaveRoom イベントを送信します。
-
プレイヤーの削除: サーバーはルームのプレイヤー リストからプレイヤーを削除し、それに応じてゲームの状態を更新します。
-
通知: サーバーは残りのすべてのクライアントに playerLeft イベントを発行し、プレーヤーがルームから退出したことを通知します。
-
UI の更新: フロントエンドは、プレーヤー リストからプレーヤーを削除し、必要に応じて進行中のゲーム メカニクスを調整することで、この変更を反映します。
単語の選択
単語の選択と誰の順番を選択するかを管理するには、いくつかのメカニズムが必要です。
-
現在のプレイヤーターン:
-
ターン管理: サーバーは、誰が単語を選択する順番であるかを記録します。これはゲームの状態によって管理され、現在のプレイヤーの ID を示すプロパティが含まれます。
-
単語選択プロンプト: プレーヤーが単語を選択する番になると、プレーヤーはサーバーからchooseWord イベントを受け取り、単語を選択するように求められます。
-
単語漏れの防止:
-
ターン制限付きアクセス: 選択した単語はすぐには他のプレイヤーにブロードキャストされません。代わりに、不当な利益を防ぐために、引き出し者の順番が来たときにのみ共有されます。
-
イベント発行: ドロワーが単語を選択すると、サーバーは wordChosen イベントをすべてのプレイヤーに発行します。このイベントには、単語が選択され、推測する準備ができているという通知が含まれます。
-
単語選択の通知:
-
ブロードキャスト: wordChosen イベントには、単語が選択されたという通知が含まれており、ルーム内のすべてのプレイヤーに送信されます。
-
フロントエンド処理: クライアント側では、プレイヤーが更新されて描画フェーズが開始されたことが示され、推測を開始できるようになります。
単語選択のタイムアウトの処理
現在のプレーヤーが単語の選択を遅らせる可能性がある場合に対処するには:
-
自動割り当て:
-
タイムアウトメカニズム: サーバーは、プレーヤーが単語を選択する番になったときに開始するタイマーを実装しています。プレーヤーが割り当てられた時間内に単語を選択しなかった場合、タイムアウト イベントがトリガーされます。
-
単語の割り当て: サーバーは事前定義されたリストから単語を自動的に選択し、プレーヤーに割り当てます。これにより、不必要な遅延なくゲームが続行されます。
-
通知: その後、wordChosen イベントが発行され、単語が割り当てられ、描画フェーズが開始されることがすべてのプレイヤーに通知されます。
図面データの取り扱い
描画データの処理は、プレイヤー間の同期を維持するために不可欠です:
-
リアルタイム描画:
-
描画イベント: プレイヤーは描画イベントを使用して描画データをサーバーに送信します。このデータには、ブラシの色、半径、描画点の座標が含まれます。
-
ブロードキャスト: サーバーはこのデータを受信し、drawData イベントを使用してルーム内のすべてのクライアントにブロードキャストします。これにより、すべてのプレイヤーのキャンバスが最新の描画情報でリアルタイムに更新されます。
プレイヤーの推測イベントの処理
プレイヤーの推測の管理には、各推測の処理と検証が含まれます。
-
推測提出:
-
イベント処理: プレーヤーが推測を行うと、推測した単語を含む推測イベントをサーバーに送信します。
-
検証: サーバーは推測を処理し、正しい単語と比較してチェックします。推測が正しければ、サーバーはゲームの状態とプレイヤーのスコアを更新します。
-
ブロードキャスト結果:
-
推測結果: サーバーは、推測が正しかったかどうかを示す推測イベントをすべてのプレイヤーに発行します。
-
UI の更新: フロントエンドでは、結果がすべてのプレイヤーに表示され、誰が正しく推測したかが示され、ゲームの進行状況が更新されます。
描画と推測のタイムアウト
時間の制約を管理することは、ゲームを魅力的に保つための鍵です:
-
ドロータイムオーバー:
-
時間管理: 各ラウンドには抽選の制限時間が設定されています。サーバーはこの時間を追跡し、時間が経過するとturnEndedイベントをトリガーします。
-
移行: このイベントは描画フェーズの終了を通知し、ゲームは推測フェーズまたは次のラウンドに移行します。
-
全プレイヤーが推測:
-
推測完了: 制限時間内にすべてのプレイヤーが単語を推測すると、サーバーは早い段階でターン終了イベントをトリガーします。
-
ゲーム フロー: このイベントは、推測フェーズが完了したことをすべてのクライアントに更新し、ゲームを次のフェーズまたはラウンドに移行します。
ゲームの状態を管理するこのアプローチにより、すべてのプレイヤーにとってスムーズでインタラクティブで公平なエクスペリエンスが保証され、ゲーム全体の楽しさが向上します。
結論
Skribbl.io クローンの構築には、リアルタイム通信、ゲーム状態管理、ユーザー インタラクションの複雑な相互作用が含まれます。このプロジェクトを通じて、私たちはプレイヤーの接続や単語の選択の処理から、描画データやプレイヤーの推測の管理に至るまで、ゲーム開発のさまざまな側面を検討してきました。
重要なポイント
-
リアルタイム通信: Socket.IO を活用することで、シームレスでインタラクティブなゲームプレイが可能になり、すべてのプレイヤーが確実に同期を保つことができます。
-
状態管理: プレイヤーの参加、単語の選択、データの描画などのゲーム状態の効率的な処理は、スムーズなユーザー エクスペリエンスにとって非常に重要です。タイムアウトと自動割り当てを実装することで、ゲームが中断されることなく確実に進行します。
-
ユーザー エクスペリエンス: 魅力的で応答性の高いインターフェイスを維持することで、プレーヤーの満足度が向上します。描画や推測などのアクションに関する明確なフィードバックとタイムリーなアップデートを組み合わせることで、プレイヤーは常に最新情報を入手し、ゲームに集中することができます。
次のステップ
このプロジェクトをさらに進めたい場合は、次のことを検討してください。
-
新機能の追加: 追加のゲーム モード、カスタマイズ、機能強化を実装して、ゲームをよりダイナミックにします。
-
パフォーマンスの最適化: 描画データ送信の最適化や遅延の削減など、パフォーマンスを向上させる方法を検討します。
-
UI/UX の強化: プレーヤーのフィードバックに基づいてユーザー インターフェイスとエクスペリエンスを改良し、ゲームをより楽しくします。
このプロジェクトは、リアルタイム ゲーム開発へのエキサイティングな旅であり、さまざまなテクノロジとテクニックを組み合わせて、楽しく魅力的なマルチプレイヤー エクスペリエンスを作成しました。この記事がゲームの状態管理に関する貴重な洞察を提供し、ゲーム開発の世界をさらに探求するきっかけになったことを願っています。
このプロジェクトに関するご意見、ご質問、改善点などを以下のコメント欄でお気軽に共有してください。コーディングを楽しんでください!
以上がSkribbl.io クローンの構築: コンセプトから完成までの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。