はじめに
本記事はスマートスピーカー Advent Calendar 2020の10日目の記事ですが、20日目の記事を書く際に発見した事をもう少し共有してみようと思い、20日目の後に書きました。
お題
SetValueコマンドで値を設定するとき、
実行する場所
と取得元
と設定先
がみんな違う時、どうするか?
です。
今回の例は1つのキャラを実装するところまでのコードですが、実際のゲームではキャラクタ同士の衝突判定など、「ゲーム進行役の処理」が必要になってきます。ここでもhandleTickを使うことを考えた際、それぞれのバインド変数がそれぞれのコンポーネントにあるため、「キャラクタのバインド変数が取れない」という壁にぶつかります。
以下のように記述することで、任意の場所のバインド変数を任意のコンポーネントのバインド変数に突っ込むことが出来ます。
例えば・・・
**"from"というIDを持つコンポーネントの"departure"というバインド変数
**に入っている値を
**"to"というIDを持つコンポーネントの"arrival"というバインド変数
**に代入する
という処理を、
**LambdaからのExecuteCommandディレクティブ
**で行ってみたいと思います。
実践
1:下準備
mainTemplate内、一番大元のContainerコンポーネントに名前を付け(ここでは"root")、バインド変数に以下のように定義します。
{
"type": "Container",
"id": "root",
"bind": [
{
"name": "G_var1",
"value": 0
}
]
}
※ 正確には、後述の取得元
と設定先
が含まれるコンポーネントであればOKです。
2:取得した値を仮置き場に代入
一旦1で作ったバインド変数に値を入れます。
{
"type": "SetValue",
"componentId": "from",
"property": "G_var1",
"value": "${event.target.bind.departure}"
}
G_var1は一番大元のコンポーネントのバインド変数なので、いわばグローバル変数のようなスコープとなり、どのコンポーネントからでも参照可能となっています。
(「ExecuteCommandディレクティブという場所」からG_var1を参照しているのではなく、「fromというIDのコンポーネント」からG_var1を参照している点に注意)
componetIdで指定したコンポーネントのバインド変数を取得するには、"event.target.bind.~"で取得可能です。
3:仮置き場の値を設定先に代入
(2に続けて)1で作ったバインド変数から値を取り出し、目的の場所に設定します。
{
"type": "SetValue",
"componentId": "to",
"property": "arrival",
"value": "${G_var1}"
}
できました!
要は、
- グローバル変数(のようなもの)を作って、A⇒tmp⇒Bと2段階代入する
ということです(おっと1行で説明できてしまったぞ・・・)。
あとがき
ここまでくるとネタというか大道芸のレベルに突入してそうな気もします…
複数の場所で使う場合はそのぶん変数を用意するなど、値の混在に特に気を付けましょう。特にその場でバインド変数があてがえないrenderdocument直下のonMountやLambdaからのexecutecommandディレクティブで重宝するかも?
「なんでそんな事しないといけないの?」と思う方が多いと思いますが、実際に行き詰った方は共感して頂ける…はず…例えば"value": "${component.from.bind.departure}"などといったようにバインド変数を取得したいコンポーネントIDを直接指定できればなぁ。(念のためですがそのような記法は存在しないので後で検索で見つけて喜ばないでね)
以上です!