等速運動だった場合の位置を、三角関数でずらす方法で実装してみた。
まず、イージングのための親関数がこれ
package com.toritoriworks.utils {
public class Easing extends Object {
protected var _x0:Number;
protected var _frame:Number;
protected var _vx:Number;
protected var _Asin:Array = new Array();
protected var _pos:int;
public function Easing(start:Number,end:Number,frame:int) {
_frame = frame;
_x0 = start;
_vx = (end-start) / (frame-1);
initialize();
}
public function initialize():void {
_pos = 0;
}
public function forward():Number {
var pp:Number;
if (isMoving()) {
pp = _x0 + _pos * _vx - _Asin[_pos];
_pos++;
} else {
pp = _x0 + (_frame-1) * _vx - _Asin[_frame-1];
}
return pp;
}
public function isMoving():Boolean {
return _pos;
}
}
}
これを派生して、以下のようなクラスを作る。
package com.toritoriworks.utils {
public class OneEndsEasing extends Easing {
public function OneEndsEasing(start:Number, end:Number, frame:int, easing:Number) {
super(start,end,frame);
var e:Number = easing < -1? -1 : ((easing > 1) ? 1 : easing);
var w:Number = Math.PI / (frame-1);
var a:Number = e * _vx / Math.sin(w);
for(var i:int = 0;i < frame;i++) {
_Asin.push(a * Math.sin(w * i));
}
}
}
}
以下のようにして作成されたインスタンスで、forwardメソッドは、呼ばれるたびに次の座標を返してくれる。
var myEasing = new OneEndsEasing(0,100,24,-1);
addEventListener(EVENT.ENTER_FRAME, frameHandler);
function frameHandler(event:Event):void {
myMovieClip.x = myEasing.forward();
}
この場合、起点を0、終点を100として、x座標が24フレームの間に、増えていく。徐々に動き出し、終点では、ピタッと止まる。
仕組みは、以下のとおり。等速直線運動(青い線)の動きに、sin関数(赤い線)の動きが足しあわされている。その結果が、緑の線である。グラフは、時間に関する位置のグラフなので、傾きは速さを表している。緑の線は、ほぼ横ばいにスタートしているので、速さはほぼゼロでスタートしていることになる。徐々に加速し、終点で最高速に達し、ピタッと止まるわけだ。sin関数の振幅は、速度が負にならず、効果が最大になるように調整されている。それが、コンストラクタの最後の引数。-1を与えると効果が最大になる。-1以下の値を与えても、-1として動作する。0でイージングの効果がでなくなる。
次のグラフは、起点、終点、およびフレーム数が同じだが、終点付近で徐々に減速し、止まる例。
var myEasing = new OneEndsEasing(0,100,24,1);
インスタンス作成の部分を上記のようにすればよい。1より大きな値を与えても、1として動作する。0でイージングの効果がでなくなる。
親クラスであるEasingクラスは、直接インスタンス化できてしまうが、意味を成さない。そのインスタンスを使用すると、_Asinが空なので、エラーが発生する。これを回避するコードは、このテーマの本質ではないので、割愛した。
0 件のコメント:
コメントを投稿