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. 一种更有效的方法是直接在 Sprite 上模拟补间,通过一个 enterframe 侦听器和一个类似于Strong.easeOut在补间中使用的函数来插入坐标。然后,您将摆脱 TweenMax 库中包含的所有额外框架,并完全控制事件和代码流。然而,这是一些模拟悠悠球行为、时间设置行为、帧率行为(您可以切换到“时间=帧”方法,消除其中一个问题)和缓动行为的一些工作。将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 回答