概要
RPGアツマールには非同期ネットゲームを想定したAPIが存在します
「グローバルシグナル」を使ってレイドバトルを作ってみたのでその解説になります
グローバルシグナルについて
- 公式
- 以前書いた記事
- [RPGアツマールのグローバルシグナルについて][link1]
- 基本的な動き方のイメージはこちらに書いてあります
[link1]:https://qiita.com/shirogane/items/4b5616d0225cb9d68a5c
作ったもの
- レイドバトル(エンディング後の要素にしています)
仕様
高HPなボスが出現して、他のプレイヤーも戦闘に参加し、協力してそのボスを倒す
というのを実現します
具体的な仕様は下記のとおりです
- ボスについて
- ユーザー1人につきボスが1体出現する
- 出現から24時間経過で消滅する
- ボスを倒した、もしくは、消滅したら、翌日に次のボスが出現する
- 曜日によって出現するボスが変わる
- 他のプレイヤー
- 出現中のボスを選んで戦闘に参加してダメージを与えることができる(これによりあるプレイヤーが他のプレイヤーのボスに対して攻撃することができる)
実装について
送信するシグナルの情報
戦闘終了時に、以下の情報を入れてグローバルシグナルを送信します
これにより、シグナルを受け取ったプレイヤーは別のプレイヤーのボスの存在を知れる状態になります
- 誰のどのボスかを識別する情報
- ユーザーID
- セーブ番号
- ボスのレベル(倒せた場合に次回出現時に1上がる)
- 戦闘結果
- ボスに今回与えたダメージ
- ボスの残りHP
- ボスの情報
- 敵グループID
- 出現した時間(UnixTimeから「時」を算出する)
{"id":101,"sig":[00000,1,14,999865792,134208,196,434706]}
戦闘結果に応じて配列に詰めてこのようなjsonを送信しています
シグナルは100byteの制限があるので収まるように注意してデータの内容を決めます
誰のどのボスかを識別する
誰の**(ユーザーID)どのセーブの(セーブ番号)どのボス(ボスのレベル)**か、
によって、誰のどのボスかを一意に識別しています
「戦闘結果」のところに書いたHPの計算をするために、シグナルが来たときにどのボスに対してダメージを与える計算をするかに使います
1つのゲームで複数のセーブデータを許す場合、ユーザーIDだけだと一意に識別することができなくなります。ゲームの仕様次第ですが、ゲーム開始時に現在時刻などからハッシュを作ってセーブデータを一意に判別できるようにするなどをやっておくとよいです。今回実装したゲームでは、セーブは複数できるけど途中でセーブ番号が変えられないような仕様にしています。
ただ、この辺ややこしくなりそうならセーブデータは1個しか保存できないようにした方がシンプルになるかと思います。
戦闘結果
シグナルの受け取り側がボスの状況を再現するのに必要な情報を入れます
そのために必要な情報が
**「誰が何ダメージ与えたか」「合計何ダメージ与えられて残りHPがいくつか」**です
必要な理由はそれぞれ以下の通りです
-
「誰が何だダメージ与えたか」
- シグナルを受ける側は与えたダメージの情報を単純に引くことで、残りHPを計算します。同じボスに対して2人3人4人など複数が同時に攻撃をしかけた場合にはこれの合計値が使われることになります
-
「残りHPがいくつか」
- すべてのグローバルシグナルは受け取れない可能性があることを考慮しなければならないため、1個のシグナルで1体分のボスを表現できるようにします。そのため「残りHP」の情報も含めています
後は、
シグナルを受け取る度に、以下の2つの計算結果から残りHPが小さくなる方を採用して、自分の手元にあるボスの情報を更新します
- 手元のボスの残りHPから与えたダメージを引く
- シグナルに含まれた残りHP
これにより、ダメージがより進んでいる方が採用されます
ボスの情報
-
敵グループID
- 曜日ごとにボスを変えるため、敵グループIDを入れておきます
-
出現した時間
- ボスが出現した時点でUnixTimeの年月日時分秒...の内、「時」を記録しておきます。出現から24時間経った時点で倒せていなかったら消滅した判定をします
まとめ
他プレイヤー間のボスを表現するために必要な情報をこのようにしてグローバルシグナルで実装できました
これによりレイドバトルをグローバルシグナルで実現しています