概要
RPGアツマールには非同期ネットゲームを想定したAPIが存在します
その中の「ユーザーシグナル」を使ってみた記事です
ユーザーを指定していいね!を送ってみました
作ったもの
- 最近遊んだユーザー一覧を取得して指定したユーザーにいいね!を送る
シグナルとは
ユーザー間での情報のやり取りを、シグナルという機能によって行えます
シグナルには100byte以内の情報(文字列)を入れることができます
例えば、送り側で以下のようなjsonの文字列を作って送信します
{ SignalId:1, SaveIdx:1, GoodId:2 }
受け側ではシグナルを取得すると送られた上記の文字列を取得できます
jsonを解釈することで、送り側から送られたSignalIdとSaveIdxとGoodIdの値が分かるという流れです
送り側のユーザーIDや名前はこれとは別に付与されているので含めなくて大丈夫です
ユーザーシグナルの動き
ユーザーIDを指定して特定のユーザーに向けて送る
「ユーザーシグナル」の動きを解説します
送り側は
window.RPGAtsumaru.experimental.signal.sendSignalToUser()
を実行します
サーバーに蓄積されていくイメージです
受け側は
window.RPGAtsumaru.experimental.signal.getUserSignals()
を実行します
またこの後に、送り側から3件目、4件目を送信してから、
受け側でシグナルの取得を行うと、受け側では1~4件目を全部取得してしまいます
APIの実行では全部取得してしまうので、
ゲーム側で新しいシグナルだけを読みたい場合は、
どこまで取得したかの情報をクライアントで持っておく必要があります
公式プラグインのAtsumaruUserSignalExperimental.js
が、
この辺りの制御をうまくやっていて、全シグナルを取りつつ、
ゲーム側には新しいシグナルしか渡さないようになっています
公式プラグインを読み解く
AtsumaruUserSignalExperimental.js
を読み解いてみます
使う人が知っていればいい情報を書いておきます
-
プラグインコマンド
- SendUserSignal
- ユーザーシグナルを送信します。通常は
$gameVariables
の変数を送るようになっていますがJson.stringify
で文字列を作るような改造をしてしまった方が使い勝手がよいです
- ユーザーシグナルを送信します。通常は
- GetUserSignal
- 1回の実行で1件のシグナルを処理します
- サーバーから取得したシグナル全件をローカルでためておきます。それを順に読んでいます。
- ローカルで持っているシグナルが0件になったら
fetchUserSignal
が実行され、setUserSignal
で$gameVariables
にセットされます - SendUserSignalの実装をJsonを送るように変えていたら、
setUserSignal
の方はJsonを解釈するように改造しておきます
- SendUserSignal
-
どこまで読んだかの制御について
- 知らなくてもよいですがプラグインの中身はこうなっていました
-
$gameSystem
の中に、$gameSystem._userSignalStoreForRPGAtsumaruPlugin.lastPoppedSignals
というメンバが増えています - 最後に取得したシグナルがここに入っているため、以降の
getUserSignals()
の実行では、lastPoppedSignals
に保存されているシグナルのcreatedAt
を見て、どこまでをゲーム側に渡すかを制御しています -
$gameSystem
の中に定義されたものなので、最後に取得したシグナルの情報はセーブデータにも入ります - これにより続きから始めたときでも新しいものしか取得しないようになっています
全てのシグナルを取得できない可能性がある
以下のことに注意してゲームの仕様を決める必要があります
- 一定の件数/容量を超えると古いものから削除される仕様のためシグナルは全て受け取れない可能性がある
- 件数や容量の詳細は公式の制限詳細を参照してください
「いいね!を送る」を実装する
「送り側」と「受け側」の実装に分けて説明します
送り側
こういうjsonを作って送ります
{
SignalId:1, // ゲーム側で定義するシグナルの種類
SaveIdx:1, // セーブデータ番号
GoodId:2 // GoodId
}
-
SignalId
- 「シグナルの種類」が入っています
- いいねシグナルは1、ログイン通知シグナルは2を入れて・・・といった感じにゲームの方で定義しています
-
SaveIdx
- 受け側の「セーブデータの番号」です
- 複数のセーブデータがあるとどのセーブデータでも受け取ってしまうのでそれを判別できるようにする必要があったので付与しました
-
GoodId
- いいねシグナル固有の情報です
- いいね!だったら1、すごいね!だったら2、サイコーだね!だったら3・・・といった感じにゲームの方で定義しています
これをJSON.stringfy
で文字列にしてwindow.RPGAtsumaru.experimental.signal.sendSignalToUser()
で送ります
また、短時間にシグナルを送信しすぎるとAPIの制限に引っかかるので注意してイベントを組むようにします。いいね!送信のイベントの後に意図的に数秒のウエイトを入れています(演出でごまかすなりした方がユーザー体験は良いかも)
秒数の制限については公式の説明を参照してください
→ https://atsumaru.github.io/api-references/common/rate-limit
受け側
受け側はwindow.RPGAtsumaru.experimental.signal.getUserSignals()
で受け取ります
setUserSignal()
の引数のstore
が持っているsignals
(→store.signals
でアクセス)
にシグナルのデータが配列で入っています
pop()
してやると1件分のシグナルが取り出せます
createdAt: 1559966464
data: "{"SignalId":1,"SaveIdx":1,"GoodId":2}"
id: 1234567
senderId: 9876543
senderName: "Shirogane"
送り側のユーザーIDや名前も付与された状態で取り出せます
送り側が作ったデータはdata
の中にあります
- 送り側からはJsonを送るようにしてあるので
Json.parse
でsignal.data
をオブジェクトに直す - セーブデータ番号
SaveIdx
が今のセーブ番号と一致している場合だけ処理する -
SignalId
が1だったら、いいねシグナルとして処理をする -
GoodId
が2なので「すごいね!」が送られたものとして処理をする
これらを使って、
イベント側で通知のプラグインなどを使って以下のような通知を出してみます
まとめ
シグナルの仕組みの説明と、それを使っていいね!を送る実装を行いました
グローバルシグナルもほぼ同じはずなので同じように実装できると思います