🫠

Goでマルチプレイのゲームを作る(powered by Ebitengine)

2024/03/31に公開

Go言語のEbitengineというゲームエンジンでマルチプレイを実装しました。

EbitengineはGo言語で簡単にゲームを作れる優れものなのですが、サンプルゲーム等はほとんどがシングルプレイのゲームです。
今回はそんな例が少ないインターネットを介した通信を行い他者と対戦・協力するようなマルチプレイをEbitengineで実装するための検証になります。

成果物

百聞は一見に如かずなので検証のために作成したキャラクターチャットを紹介します。
https://folks-chat.com/

名前とキャラクターを選択して入室するとチャット画面に遷移し、移動やメッセージ送信をすることができます。
Ebiten Chatデモ

使用技術

Ebitengine

Go言語でゲームを作ることのできるゲームエンジンです。
非常にシンプルなAPIを使ってパフォーマンスの高い2Dゲームを開発することができます。
デスクトップアプリに加えて本記事の検証プログラムのようにWebAssemblyにしたり、他にもmobileやNintendo Switch™など多様な環境をサポートしています。
https://ebitengine.org/ja/
分かりやすいサンプルゲーム | 2048
https://ebitengine.org/ja/examples/2048.html

WebSocket

本検証ではWebSocketを用いてマルチプレイを実現しています。
WebSocketとはクライアントとサーバ間で双方向にデータをやり取りする通信プロトコルであり、リクエストとレスポンスで接続が一区切りするhttpとは異なり接続を維持することでサーバからのデータ送信をリアルタイムに受信することができます。
https://shukapin.com/infographicIT/websocket

Go言語はバックエンドが主戦場なためWebSocketサーバも容易に立てることができます。
有名なpackageはgollira/websocketがあり、検証プログラムでも本pacakgeで建てたWebSocketサーバと通信しています。
https://github.com/gorilla/websocket
ただし、gollira/websocketはWebAssembly非対応なため、今回の検証プログラムのようにGoのWebAssemblyをWebSocketクライアントとさせる際にはnhooyr/websocketなど対応packageを使う必要があります。
https://github.com/nhooyr/websocket

仕組み

WebSocketサーバさえ建てられれば今回のようなチャットは複雑なゲームルールを気にしなくていいので比較的簡単にマルチプレイを実現することができます。

例えばチャットの入室の際は以下のようなフローで通信されています。
WebSocketサーバはざっくり既存データの永続化と新しいデータの配信を担当しています。
新規に入室したユーザはサーバがDBから取得したキャラクタの新しい座標と新しいメッセージの配信を受け、他のすでに入室しているユーザと同じ画面を描画するための情報をもらいます。
また、自分がどの画像のキャラクタでどこの座標に新規に入室したかを他のユーザに伝えるためにサーバにデータを送信します
入室の処理フロー

入室後のキャラクターの移動やメッセージ送信はそれぞれ座標データ、メッセージ文字列データをサーバに送信することで他ユーザと同期しています。
メッセージは老舗のもなちゃとをリスペクトしてふわふわと浮かび上がるようになっています。
こちらはメッセージの送信時刻と現在時刻の差分を使いキャラクタから見たメッセージの高さを計算し描画することで実現しています。
メッセージ送信の処理フロー

より詳しい内容は以下で公開しているソースコードをご参照ください!
https://github.com/ponyo877/ebiten-chat

おまけ

先日開催したEbitengineのLT大会である「Ebitengine ぷちConf #2」に本記事の内容で発表しています。
https://gocon.connpass.com/event/306765/
とても参考になる発表がたくさんあったのでEbitengineに興味がある方はアーカイブ視聴をお勧めします!
発表資料
https://speakerdeck.com/ponyo877/ebitennomarutihureidui-ying-websocketnohuo-yong

配信アーカイブ(本記事については1:02:37~)
https://www.youtube.com/live/DUX7r-gZsaI?si=nVqZWp2zt40HVNDJ

Discussion