Goでマルチプレイのゲームを作る(powered by Ebitengine)
Go言語のEbitengineというゲームエンジンでマルチプレイを実装しました。
EbitengineはGo言語で簡単にゲームを作れる優れものなのですが、サンプルゲーム等はほとんどがシングルプレイのゲームです。
今回はそんな例が少ないインターネットを介した通信を行い他者と対戦・協力するようなマルチプレイをEbitengineで実装するための検証になります。
成果物
百聞は一見に如かずなので検証のために作成したキャラクターチャットを紹介します。
名前とキャラクターを選択して入室するとチャット画面に遷移し、移動やメッセージ送信をすることができます。
使用技術
Ebitengine
Go言語でゲームを作ることのできるゲームエンジンです。
非常にシンプルなAPIを使ってパフォーマンスの高い2Dゲームを開発することができます。
デスクトップアプリに加えて本記事の検証プログラムのようにWebAssemblyにしたり、他にもmobileやNintendo Switch™など多様な環境をサポートしています。
分かりやすいサンプルゲーム | 2048
WebSocket
本検証ではWebSocketを用いてマルチプレイを実現しています。
WebSocketとはクライアントとサーバ間で双方向にデータをやり取りする通信プロトコルであり、リクエストとレスポンスで接続が一区切りするhttpとは異なり接続を維持することでサーバからのデータ送信をリアルタイムに受信することができます。
Go言語はバックエンドが主戦場なためWebSocketサーバも容易に立てることができます。
有名なpackageはgollira/websocketがあり、検証プログラムでも本pacakgeで建てたWebSocketサーバと通信しています。
ただし、gollira/websocketはWebAssembly非対応なため、今回の検証プログラムのようにGoのWebAssemblyをWebSocketクライアントとさせる際にはnhooyr/websocketなど対応packageを使う必要があります。
仕組み
WebSocketサーバさえ建てられれば今回のようなチャットは複雑なゲームルールを気にしなくていいので比較的簡単にマルチプレイを実現することができます。
例えばチャットの入室の際は以下のようなフローで通信されています。
WebSocketサーバはざっくり既存データの永続化と新しいデータの配信を担当しています。
新規に入室したユーザはサーバがDBから取得したキャラクタの新しい座標と新しいメッセージの配信を受け、他のすでに入室しているユーザと同じ画面を描画するための情報をもらいます。
また、自分がどの画像のキャラクタでどこの座標に新規に入室したかを他のユーザに伝えるためにサーバにデータを送信します
入室後のキャラクターの移動やメッセージ送信はそれぞれ座標データ、メッセージ文字列データをサーバに送信することで他ユーザと同期しています。
メッセージは老舗のもなちゃとをリスペクトしてふわふわと浮かび上がるようになっています。
こちらはメッセージの送信時刻と現在時刻の差分を使いキャラクタから見たメッセージの高さを計算し描画することで実現しています。
より詳しい内容は以下で公開しているソースコードをご参照ください!
おまけ
先日開催したEbitengineのLT大会である「Ebitengine ぷちConf #2」に本記事の内容で発表しています。
発表資料
配信アーカイブ(本記事については1:02:37~)
Discussion