# 【程序化动画の二阶系统】

把线性移动转换成顺滑的曲线运动十分有用,比如摄像机跟随玩家移动。

以下是曲线参数可视化:

module vp 
{
    /** 
     * 2D 的SOD
     */
    export class SecondOrderDynamics
    {
        private xp:Phaser.Math.Vector2 = new Phaser.Math.Vector2(0,0);
        private y:Phaser.Math.Vector2 = new Phaser.Math.Vector2(0,0);
        private yd:Phaser.Math.Vector2 = new Phaser.Math.Vector2(0,0);
        private k1:number = 0;
        private k2:number = 0;
        private k3:number = 0;

        constructor(f:number, z:number, r:number, x0:Phaser.Math.Vector2)
        {
            this.init(f,z,r,x0);
        }

        public init(f:number, z:number, r:number, x0:Phaser.Math.Vector2): void {
            let PI = Math.PI;
            this.k1 = z / (PI * f);
            this.k2 = 1 / ((2 * PI * f) * (2 * PI * f));
            this.k3 = r * z / (2 * PI * f);
            this.xp.x = x0.x;
            this.xp.y = x0.y;
            this.y.x = x0.x;
            this.y.y = x0.y;
            this.yd.x = 0;
            this.yd.y = 0;
        }

        /** 
         * T:每帧经过的时间
         * 
         */
        public update(T:number,x:Phaser.Math.Vector2,xd:Phaser.Math.Vector2 = null):Phaser.Math.Vector2
        {
            if(xd == null){
                xd = new Phaser.Math.Vector2();
                xd.x = (x.x - this.xp.x) / T;
                xd.y = (x.y - this.xp.y) / T;

                this.xp.x = x.x;
                this.xp.y = x.y;
            }
            let k2_stable = Math.max(this.k2, T*T/2 + T*this.k1/2, T*this.k1);
            this.y.x = this.y.x + T * this.yd.x;
            this.y.y = this.y.y + T * this.yd.y;
            this.yd.x = this.yd.x + T * (x.x + this.k3*xd.x - this.y.x - this.k1*this.yd.x) / k2_stable;
            this.yd.y = this.yd.y + T * (x.y + this.k3*xd.y - this.y.y - this.k1*this.yd.y) / k2_stable;
            return this.y;
        }
    }
}