1

AS3 でベジエ曲線をアニメーション化する最良の方法を見つけようとしています。これまでのところ、以下が最良の解決策です。

import flash.display.*;
import flash.display.Sprite;
import flash.geom.*;
import com.greensock.TweenMax;
import com.greensock.easing.*;

public class Waves extends MovieClip
{

    public var piste:Number = stage.stageHeight;
    public var piste2:Number = 0;

    var a:Sprite = new Sprite();
    var coord:Vector.<Number> = new Vector.<Number>();
    var com:Vector.<int> = new Vector.<int>();

    public function Waves()
    {

        addChild(a);

        coord.push(0, 30);
        com.push(1);
        coord.push(260, piste, stage.stageWidth, 30);
        com.push(3);

        tweenNumbers();

    }

    public function tweenNumbers():void {

            TweenMax.to(this, 0.45, {piste:piste2, repeat:-1, yoyo:true, immediateRender:true, ease:Expo.easeOut, onUpdate:draw});

    }

    public function draw():void {

        coord[3] = piste;
        a.graphics.clear();
        a.graphics.lineStyle(1,0x990000,1);
        a.graphics.drawPath(com, coord);


    }

}

曲線をアニメーション化するには、本当に graphics.clear を使用する必要がありますか? より効率的な方法はありますか?1 秒より速くトゥイーンすると、レンダリングが遅くなり、前の行が表示されます。それを取り除く方法はありますか?

4

1 に答える 1

1

うーん。おそらく、問題を適切にデバッグするために、TweenMax の使用バージョンを投稿する必要があります。それらにはいくつかあるようで、非同期にディスパッチされた「更新」イベントを使用するものもあれば、enterframe リスナーを使用するものもあり、各更新ルーチンが各フレームで呼び出されるようにします。そのため、非同期シナリオではグラフィックスのジッターが発生する可能性があります。

他の質問について:

  1. はい、問題のグラフィックス オブジェクトを再描画する必要があります。これには の呼び出しが含まれgraphics.clear()ます。Graphics オブジェクトはブラックボックス エンティティであるため、カーブのコントロール ポイントに直接到達してトゥイーンすることはできません。したがって、曲線上の点を変更するには、それを再描画する必要があります。

  2. Strong.easeOutより効率的な方法は、Enterframe リスナーと、座標を補間するためにトゥイーンで使用されるのと同様の関数を介して、スプライトでトゥイーンを直接エミュレートすることです。その後、TweenMax ライブラリに含まれる余分なフレームワークをすべて取り除き、イベントとコード フローを完全に制御できるようになります。ただし、これは、ヨーヨーの動作、時間設定の動作、フレームレートの動作 (「time=frame」アプローチに切り替えて、問題の 1 つを排除できます) とイージング動作の両方をエミュレートするための作業です。は次のtweenNumbersようになります。


var isYoyo:Boolean=false;
var currentFrame:int;
var maxFrame:int;
function easingFunction(frame:int,maxframe:int,a:Number,b:Number):Number { 
    var x:Number=Number(frame)/maxframe;
    return a+(b-a)*(x*x*(3-2*x)); // 3x^2-2x^3, a double-easing Perlin function
    // recreate your needed function here!
}
var piste1:Number=0; // storing start coordinate
private function tweenNumbers():void {
    maxFrame=Math.round(0.45*stage.frameRate); // from seconds to frames
    currentFrame=0;
    isYoyo=false;
    a.addEventListener(Event.ENTER_FRAME,onUpdate);
}
private function onUpdate(e:Event):void {
    if (!isYoyo) {
        currentFrame++;
        if (currentFrame==maxFrame) isYoyo=true;
    } else {
        currentFrame--;
        if (currentFrame==0) isYoyo=false;
    } // advance time
    coords[3]=easingFunction(currentFrame,maxFrame,piste1,piste2);
    // tween the coords[3] manually
    a.graphics.clear();
    a.graphics.lineStyle(1,0x990000,1);
    a.graphics.drawPath(com, coord);
    // draw updated path
}

ただし、非同期化の保証はありませんが、通常は機能します。また、ステージのフレームレートを高く設定しすぎた場合、非同期 (前の行を参照) が発生する可能性があるため、ターゲット デバイスのビデオ サブシステムは一度に多くのフレームを描画できません。

于 2013-08-12T05:40:57.967 に答える