レトロゲーム風の意演出ではキャラクターがスムーズに動くのでなく、数ドットごとにカクカクと動く方が演出的に好ましいことがある。アニメーションカーブで実現する事もできそうだがこれをエクスプレッションで実現する。
上がアニメーション設定そのままの例で、下がそれにエクスプイレッション制御を与えたもの。※残像はオマケです。
なお今回のコード例を使わなくてもそのものずばりのエフェクトや関数がビルトインにあるのではないか??という気はする。自分はさらに機能を追加していって使う予定なので自作している。
簡単なコード例

p = transform.position.value;
step = 16;
p[0] = Math.floor(p[0] / step) * step;
p[1] = Math.floor(p[1] / step) * step;
p;
16ドットごとに吸着させたい場合は上のコードのようになる。簡単だがこの座標値を他のエクスプレッションで参照する場合、吸着した座標で値が得られるのは注意が必要である。それが望ましいことも望ましくない事もある。ガタガタ吸着する前の元の値を取る必要がある場合は、べつのNULLオブジェクトなどでスムーズな座標のアニメーションは設定し、その値をキャラクターの座標側取得しグリッド吸着させるなどする。
なぞのプルプル不具合への対処
上のままのコードではキャラクターが上下にプルプルと震えることがあった。これはAEのアニメーションがたとえ真横のみの移動であってもごく小さな値で誤差が入る事があるからであった。これをさけるには四捨五入の処理を入れる。
p[0] = Math.floor((p[0] + 0.5) / step) * step;
汎用化
たくさんキャラクターが表示される場合、毎回同じコードを張るのは調整が効かず再利用もしずらいので外部jsxファイルに処理を記述してエクスプレッションからはそれを呼び出すようにした。この場合メディアエンコーダーでレンダリングするとエクスプレッションが無効になるようなのでメディアエンコーダーを使いたい場合は我慢してスニペットをエクスプレッションにコピペなどの対応を取る。
fakegame.jsx
{
grid_snap: function(values, size=8){
if(typeof values == "number"){
return Math.floor((values + 0.5) / size) * size;
}
a = [];
for(i in values){
a.push(Math.floor((values[i] + 0.5) / size) * size);
}
return a;
}
}
引数はxyz座標どれかの単独でもポジション値全てでも動くようにしてある。
エクスプレッションからの呼び出し
p = transform.position.value;
footage('fakegame.jsx').sourceData.grid_snap(p);
jsx呼び出しはもっとすっきりかけないものか。
import fakegame.*;
grid_snap(p);
とか書きたいところ。



