時間→座標の補間関数を工夫する
前項のサンプルは 単に時間の経過に合わせ直線的に値を増減させるものでした。
物理的な運動ではいきなり特定の速度に達することは無く加減速のステップがあります。
くるまが停止状態からスピードを上げ 目的地に近くなったらスピードを落とすように
レイヤーの移動を工夫してみましょう。
【補間関数を用いたレイヤーの移動アニメーション】
-----------------------------------------------------------------------------
■ hokan(r,zs,ze,f,ts,te):
・返り値:「zs〜ze」の値を関数「f」と比率「r(0〜1)」で補間
「r=0」時は「z=zs」、「r=1」時は「z=ze」を返す
■ move(id,xs,ys,xe,ye,f,ts,te):
・レイヤー「id」を(xs,ys)から(xe,ye)へ移動するのに使う関数
タイマー関数「kl_timer_start()」に登録して使用
-----------------------------------------------------------------------------
function f(t){
//線形補間
return t;
}
function hokan(r,zs,ze,f,ts,te){
//r=[0:1]の値を同じく[0:1]に関数fで射影します
r=(f((te-ts)*r+ts)-f(ts))/(f(te)-f(ts));
return (ze-zs)*r+zs;
}
function move(id,xs,ys,xe,ye,f,ts,te){
//r=[0:1]の値になります
var r=this.kl_cnt/(this.kl_reps-1.0);
//x,y座標を補間して求めます (適宜最適化してください)
x=hokan(r,xs,xe,f,ts,te); x=Math.round(x);
y=hokan(r,ys,ye,f,ts,te); y=Math.round(y);
//レイヤーを算出した位置に移動します
kl_layer_moveto(id,x,y);
}
x0=kl_slx()+10; y0=kl_sly()+10;
x1=kl_slx()+400; y1=kl_sly()+400;
//レイヤー「lay1」を30msec毎に100回移動する
kl_timer_start(move,new Array("lay1",x0,y0,x1,y1,f,-1,1),30,100);
補間用関数「hokan()」に渡す
関数「f(t)」と区間「ts,te」を変えることによって 動作をカスタマイズできます。
まず上の例を実行して見ましょう。
最初の例は加減速無しで普通に等速運動するものです。
補間の設定は関数「z=t」を区間「-1〜+1」で使っています。
タイマー機能を簡単に利用:kl_timer_...()
を使い移動関数「move()」を30msec毎に100回呼び出しています。
レイヤー「lay1」です。
次は工学でお馴染み?の「z=(e(t)-1)/(e(t)+1)」を使ってみます。
原点対象(z(-t)=-z(t))、t→無限大で1に漸近、t→無限小で-1に漸近という特徴があります。
あまり加減速しませんね。
区間を広げて[-10:10]にしてみましょう。
いい感じですね。
今度は区間を[-30:10]にして非対称で利用してみましょう。
逆に[0:20]にしてみます。始めは速く 目的地に近くなったら遅くなります。
今度は「sin」関数の例です。
これだけでは あまり加減速しないので
3階の合成関数にしてみましょう。
随分変わりましたね。
今度は「t**0.3」(0.3乗)にしてみましょう。
今度は 上の関数の逆関数を利用して
パスの真ん中で速度が落ちるようにしてみましょう。
今度は5乗に。
これまで見てきたように「hokan()」に渡す関数「f(t)」とその利用区間「ts,te」を
変えることによって移動アニメーションをカスタマイズできます。
3つ以上の通過点を指定したい
さて、これまでの例は単に開始点・終了点の2点間を直線的に移動するものでした。
一方、3点以上の通過点を用意して それらを
滑らかに通過したい場合もあるでしょう。
その場合は BezierやNurbsなどスプライン系の関数で軌道を計算します。
曲線パラメータを線長にすればこれまでの
アニメーションの工夫がそのまま使えます。
興味がある人は調べてみて下さい。