2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

enebularAdvent Calendar 2021

Day 23

enebularのwebsocketノードで対戦ゲームを作ってみる

Last updated at Posted at 2021-12-22

#一人用鬼ごっこを通信対戦ゲームにしたい
この記事はenebular Advent Calendar 2021の23日目の記事なります。

以前、p5jsを使った一人用のかくれんぼゲームを作ってみました。
上下左右操作+Aキー/Fキー操作で、移動しながらプレイヤーの色を変えられ、背景の色になじむことができます。
なじんでいる間は鬼は見失い、なじまなくなったら全力で追いかけてくる鬼ごっこです。

この時は鬼はロジックで組まれたコンピュータだったのですが、どうにか通信対戦できないか、と考えwebsocketの勉強を始めました。
そんな中、enebularにwebsocketのノードがあること知り、これを使えばサーバーサイドはノーコードで実装できるのでは・・・?と思いトライしてみました。

是非是非ご覧ください!

#完成デモ
アクセスした直後にplayer or oniと聞かれるので、逃げる側の場合はplayer、鬼側の場合はoniと記入します。
左側のブラウザ操作 (逃げる側)の動きが、多少のラグを伴って右側のブラウザ (鬼側)に伝わっているのが分かりますね。
これができるなら結構いろんなゲームが作れそう。

#実装こまごま
##そもそもwebsocketとは?
そもそもwebsocketって何じゃらという話はこの記事が分かりやすかったので是非ご覧ください。
ザクっと、一方向のHTTPと違って、双方向通信を実現してくれるのがwebsocket。
通信対戦ゲームを作るときによく使うプロトコルみたいです。

##クライアント側の実装
実装はこのサイトを参考にしました。
今回は標準のWebsocketライブラリを使ってみました。
Websocketの部分のコードはこんな感じです。
Websocketの接続先はデプロイしたenebularの情報からインプットし、逃げる側は/nigeru、鬼側は/oniに接続するように設定しました。

      var ws = null;
      
      //playerかoniか選んでもらう
      var player_or_oni = window.prompt("player or oni")
      var ws_url = "ws://(enebularから情報を取ってくる).herokuapp.com/ws/"

      //それぞれパスを付け足す
      if (player_or_oni =="player"){
          ws_url += "nigeru";
      }else{
          ws_url += "oni";
      }

      // ベースのURL+WebSocketのパスでつなげる
      ws = new WebSocket(ws_url);
      // WebSocket が接続された open イベント設定
      ws.onopen = hanlderWebSocketOpen;
      // WebSocket からメッセージを受け取った message イベント設定
      ws.onmessage = hanlderWebSocketMessage;

      // WebSocket が接続された open イベント
      function hanlderWebSocketOpen(event) {
          ws.send('Hello! Node-RED!');
      }

      // WebSocket からメッセージを受け取った message イベント
      function hanlderWebSocketMessage (event) {
        var res = JSON.parse(event.data)
        console.log("中身は:",res["p_or_o"] )
      }

      async function  hanlderSendMessage(_player_or_oni) {
        //自分で操作した場合は情報を送る
        if (_player_or_oni == player_or_oni){
          // JSON データは JSON.stringify で文字列にしてから送っています
          var _message = { content: message, p_or_o : player_or_oni };
          await this.ws.send(JSON.stringify(_message));
        }
    }

この基本を押さえたうえで、通信のイメージはこんな感じ。
一方のプレイヤーが操作した情報を、enebular経由で他方のプレイヤーに伝えるスキームを考えました。
image.png

##enebular上のフロー
フローはこんな感じ。
素直に送られてきた情報をもう一方のノードに渡しているだけになります。
image.png

websocket inノードの設定はこんな感じ。
image.png
えんぴつマーククリック後はこんな感じ。
image.png

functionノードはこんな感じ。
ここが一つのハマリポイントで、このmsg._sessionの削除をしないと、セッション保持の都合で相手に情報が伝達できなくなってしまいます。
これ知るまでに何時間もハマってしまった・・・。
image.png

jsonノードはこんな感じ。
特にトリッキーなことはしてません。
image.png

websocket outノードはこんな感じ。
websocket inとほぼ同じです。
image.png
えんぴつマーククリック後はこんな感じ。
image.png
ちなみにfunctionノードが必要になるのはwebsocket outの仕様みたいです。
一応こんな説明書きがありました。
image.png

##WebsocketのURL
enebularでフローを作った後にデプロイし、画面右上のインフォマークにマウスオーバーします。
httpsのURLが出てきますので、ここをwsに書き換えてクライアント側に実装すればOK。
image.png

#最後に
今回はenebularのwebsocketノードを使って対戦ゲームを実装してみました。
サーバーサイド側がシンプルなので、クライアント側の実装に集中できそうですね。enebularすごい。

今回の実装だと、部屋分けをして「特定の誰か」と「特定の誰か」で戦う、みたいな要件が実現できません。
部屋分けを実現する場合別のライブラリが必要になりそう。

おいおい勉強してみようと思います!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?