スクラッチに挑戦している皆さん、どうも!スクラッチコーチです。
前回はバッファリングを実装して欠落のない動きの再現に成功したぞ!これ↓がバッファリングに成功した状態だ。
変数「★送信用データ」をエンコードしてクラウド変数1に一括でセットしている様子が見て取れるね。
ここからは他プレイヤーとのクラウド変数の共有を意識した実装を進めていく。ややこしくなってきたねぇ!
今回の目標「UIDを実装して別プレイヤーを検知する」
自分と他人を区別するためにUID(=ユニークID)を実装していこう。これを使えば誰がクラウド変数を更新したのか分かるようになるんだ。
今のままだと、別タブで同じ作品を開いてみるとタブAでもタブBでもクラウド変数1を更新するため、誰の座標データなのか識別不能な状態なんだ。そこで今回は、クラウド変数1に渡すデータにUIDというプレイヤーを識別できるデータを追加していきたいというわけ。
座標以外のデータをクラウド変数に渡す練習にもなるよ。まぁ方法は座標のときと同じ!エンコードしてクラウド変数にセットして、受け取り側ではデコードしてデータを分解して使うよ。
おっと、ただそのまえに1つやることがあるんだ。そのあたりも順番に見ていこう。
今回やることをざっくりまとめるとこう↓
- 新しいリスト「★クラウドデータ」を作る
- 長い数字を文字化する
- プレイヤーUIDを送る
- プレイヤーUIDを受け取る
- プレイヤーUIDを調べる
こんな感じで進めていくよ。
直前のクラウド変数の中身を保持するリストを作る
このあとの実装で、クラウド変数が更新されたかどうかを調べる工程がある。そこで直前のデータと最新のデータを比較しないといけないので、直前のデータを保存しておくためのリストを用意したいと思う。
リスト「★クラウドデータ」を作る
このリストに直前のデータを追加していく。
初期化する
クラウド変数の値をクラウドデータに保管しておく
これでこのあと、クラウド変数1の中身が前のティックから変わってるかどうかを判断するのに役立つ!
長い数字を比較する
しょぼーんってなるけど、ここでみんなにスクラッチの困った仕様を1つご紹介しないといけない。それは長い数字の比較に関するものだ。
例えばここに250ケタの超長い数字があったとする。(実際クラウド変数に色んなデータをエンコードしまくって入れてると長くなることはある)
これはテストだからみんなはやらなくてもいいけど、気になったらためしにやってみ。
こういう長い数字を比較してみたいと思う。
うん、ふつうに「値 = 値」はTRUE(真)だね!じゃあこれは?↓
「値 = (値 + 1)」だね。いやいや、そりゃあFALSE(偽)でしょ。当たり前じゃん。こんなん誰でも分か……
おおおおおい!?なんかTRUE(真)ってなってるんですけど!?絶対違うじゃんか……。WHY!?スクラッチピーポー!
【悲報】じつはスクラッチさん、長い数字が理解できません↓
250ケタの値に1を加算すると、スクラッチの限界を超えてしまって理解不能な数字になってしまうんです……。そしてこれを比較に使うとさっき見た通りなんでもTRUEになっちゃう……。しかもエラーにもならないっていうバグの温床でもある。アンビリーバボーだぜ!
何が困るの?
これで何が困るのかって言うと、このあとの実装で困る。このあとクラウド変数1の値が変更されたかどうかを調べていくんだけど、そのときに直前の値と現在の値を比較したいんだ。でももしデータが長すぎてスクラッチの限界を超えてたら、なんでもかんでもTRUEになっちゃうんだよね。つまり直前の値と現在の値は常に同じ(=変更なし)って判定になってしまう。これでは正しく動かないよね。
これを未然に防ぐために策を講じておきたいと思うぜ。
数字を文字に明示的に直す
長い数字が理解できないなら長い文字にすればいいじゃない?という一見するとマリー・アントワネットばりの理不尽な見解(※)だけど、スクラッチに関しては正解なんだ。
※「パンがないならケーキを食べればいいじゃない?」っていうマリー・アントワネットが言ったとされる名言(迷言)がある。ただし本人はそんなこと言ってないという説が有力。ネガティブ・キャンペーンってやつか。
明示的に数字を文字に直す方法はカンタン。文字と数字をくっつければOK。
これはアルファベットの「c」と変数「値」をくっつけてから比較してる。
(c + 値)=(c + (値 + 1))
こうすると答えはFALSE(偽)になるから正解だね。ふぅ!あっぶね。
文字化する
じゃあクラウド変数1を明示的に文字にしよう。くっつける文字は何でもいいんだけど、クラウド(Cloud)の「c」にしとこうか。
テストする
うん、cがついてて文字になってるね。文字だからもう計算には使えないけど、これを計算する予定はないので問題ない!
別タブでテストしてみる
このタイミングでまたタブを2つ開いて隣同士に並べて動きを確認しておこう。
この動画を拡大してみてみて。タブ左が動いてるときにタブ右のクラウド変数1がどんどん更新されてるよね。これはタブ左からの座標データと、タブ右自身の座標データが交互にクラウド変数1を更新しているからなんだ。つまり、2つあるデータのうち1つはタブ左のもの、もう1つはタブ右のものという状態だね。
で、どのデータがどっちのデータなのか、それを明らかにするために冒頭で伝えたUIDというものを実装していくよ。
UIDを実装する「送信編」
UID自体はランダムな数字の羅列にするよ。たとえば214843みたいな意味のない、だけど滅多に重複しない数字。
変数「★自プレイヤーUID」を作る
すべてのスプライト用に新しい変数を作ろう。
初期化する
メッセージ「クラウド - セットアップ」を受け取ったところに乱数1から9,999,999(9が7個)で初期化しよう。
これで滅多に重複しないでしょう!こんな感じ↓
エンコード文字列の先頭に追加する
今まではXとYの座標データしかエンコードしてなかったけど、これからは最初にUIDをエンコードして入れるようにするよ。ブロック定義「同期する」内にブロックを追加しよう。
これで変数「エンコード文字列」に自プレイヤーUIDがエンコードされて追加されたね。ちょっと見てみようか。
バッチリ。エンコードが正しく機能してて、なんか気持ちいい!
UIDを実装する「受信編」
自分から送るデータにプレイヤーUIDを付けることには成功した。次はクラウド変数をデコードしてプレイヤーUIDを受け取って、それが自分のものか別プレイヤーのものかを判定するところだ。
っとそのまえに1つ変更したいことがある。
ブロック定義「同期する」の名前を変える
同期するだと送信する意味も受信する意味も含まれてて、ちょっとアイマイだから名前を変えておきたい。
ブロック定義「同意する」を右クリックして編集を選ぼう。
明確に「クラウド変数を送信する」に変更しておこうかな!
ブロック定義「クラウド変数を受信する」を作る
これの対になるブロック定義「クラウド変数を受信する」を作っていこう。引数には☁《くも》番号と更新データの2つを取るようにしよう。ちなみに☁はクラウドっていう意味を込めてる。
使用する
メッセージ「クラウド - ティック」を受け取ったタイミングで使おう。
1つ目の引数に「1」を入れたね。1はクラウド変数1を意味するよ。別チュートリアルでこの1が持つ意味が明らかになるから、今はとりあえず1はクラウド変数1なんだな、って認識しておいてね。
2つ目の引数にはクラウド変数を文字化したものを入れるよ。さっきリスト「★クラウドデータ」に入れた際に文字化した処理と全く同じ演算「c + クラウド変数1」だよ。
よし、じゃあブロック定義「クラウド変数を受信する」の中を作り込んでいこう!
変更がなければ何もしない
もしクラウド変数の中身が直前の値と変わってないなら何もしないよ。
とりま「もし」ブロックをカチッと。
条件式を作る
次に、クラウド変数の中身を比較するにはリスト「★クラウドデータ」が役立つ。これはクラウド変数の直前の値が格納されているリストだったね。そして最新の値は2つ目の引数「更新データ」に入ってる。だからこの2つを比較する演算を作ってみよう。
これを条件式にハメよう。
このスクリプトを止める
で、更新されてないなら何もしなくてOKと。
変更があれば★クラウドデータを更新する
もしも変更があったら直前のデータを最新のデータで更新しよう!
テスト
クラウド変数1とクラウドデータの値が同期されるようになったね!
良きかな。
プレイヤーUIDを取得する
更新されたデータが誰のものなのか調べていこう!なにげにここはエキサイティングに感じる!だって他の人がいるかどうかってオンラインゲームにとって重要なことだもんね。
どうやって調べるのか!?そりゃデコードっしょ。デコードしてプレイヤーUIDを取得していくぞ!
エンコード文字列に値を入れる
デコードするためにはまず変数「エンコード文字列」にデコード対象となるデータを入れる必要があったね。
エンコード文字の順番を指定する
さて、この更新データの中身ってなんだっけ?さっき★クラウドデータに入れた値を見てみると「c78280511206...」ってなってるね。
前はエンコード文字の順番は素直に1文字目から始めてたけど、今って文字化で使った「c」がいるからエンコードを始めるのは2文字目からじゃないとダメだね。
そうと分かればカンタン。
マジックナンバーになってしまうのが気持ち悪いけどとりあえずOK。
デコードする
ここはブロック定義を使い回す!再利用、最高!
これで変数「値」にはプレイヤーUIDが入っていることになるね!
誰のデータなのか調べる
いよいよ誰のプレイヤーUIDが送られてきたのか調べるぞぉ!
バリデーションする
っとそのまえにデータが壊れていたり、自分自身のUIDだったりしたら処理を止めるようにガード処理を作っておこう。こういうデータの正当性を調べる作業をバリデーションって呼んだりする。
条件ブロックを置いておく
とりあえず「もし」ブロックと処理を止めるブロックを置いておこう。
条件式を作る
処理を止める条件1はデータが壊れている場合。1未満みたいな値だったら壊れていると判断しよう。
壊れない、って思っててもスクラッチは誰でも中を改変できるからね。ひょっとしたら誰かが誤った変更を加えて壊れた値が飛んでくるなんてことも十分ありえる。
あとは自分のUIDだった場合だね。
このどちらかであったら処理を止めるってしておこう。最終的にはこうなる↓
よし、締めのテストに移ろうか。
プレイヤー番号を作る
テストも兼ねて変数「プレイヤー番号」を作るよ。あとで実装でも使うから一石二鳥だよ。
初期化する
空白で初期化するよ。
配置する
あとで変えるけど、いったん変数「値」を代入して様子を見よう。
テスト
タブを並べて動かしてみよう!
おおお!タブ左のプレイヤーUIDが、タブ右の変数「プレイヤー番号」に入ってるね。逆も同じだ!完璧ぃ!これで他のプレイヤーの座標データを処理する準備が整ったというわけだ!イエス!
次回へ
今回はプレイヤーUIDを実装して別プレイヤーを検知するところが完成したね。オンラインゲームにとってまさに重要なキーポイントだったと思うよ。
今回やったことをカンタンに振り返ろう。
- 新しいリスト「★クラウドデータ」を作って、直前のクラウド変数の値を保持できるようにした
- 長い数字を文字化して、正しくデータの比較ができるようにした
- プレイヤーUIDをエンコード文字列の先頭に追加した
- プレイヤーUIDをデコードして自分以外のプレイヤーの存在を検知できるようにした
次からは別プレイヤーのデータを登録処理していこう!いよいよ100人規模の参加に耐えるオンラインゲームエンジンの完成が近づいてきたぞ。ワクワクが止まんねぇ!また2,3日で更新するので待っててね。
- ① クラウド変数の使い方
- ② エンコードする
- ③ デコードする
- ④ マイナス値に対応する
- ⑤ バッファリングを実装する
- ⑥ 別プレイヤーを検知する (いまここ)
- ⑦ プレイヤーを管理する
- ⑧ クローンを使おう
- ⑨ スケールアップする
- ⑩ 退場処理を作る
- ⑪ 自作ゲーム「鬼ごっこ」を作る
- ⑫ MMO鬼ごっこに改造する
- ⑬ クラウド変数でユーザー名を共有する方法