I've been trying to find the best way to animate bezier curves with AS3. By this far following has been the best solution:
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);
}
}
Do I really have to use graphics.clear to animate curves? Is there more efficient way? If I tween faster than 1 second, rendering lags and you can see the previous line, is there way to get rid of it?
Hmm. Perhaps you should post your used version of TweenMax to properly debug the issue. There seem to be several of them, some use asynchronusly dispatched "update" events, some employ an enterframe listener, thus making sure each update routine is called each frame. So, graphics jittering can occur in an asynchronus scenario.
On the other questions:
Yes, you have to redraw the graphics object in question, this involves calling graphics.clear()
. See, the Graphics object is a blackbox entity, you can't directly reach a control point of a curve to tween it somehow. So, in order to change a point on a curve, you have to redraw it.
A more efficient way would be emulating a tween on your Sprite directly, via an enterframe listener and a function similar to Strong.easeOut
used in tweening to interpolate coordinates. You will then get rid of the all extra framework included in TweenMax library and will get full control of the event and code flow. This, however, is some work to both emulate yoyo behavior, time setting behavior, framerate behavior (you can switch to "time=frame" approach, eliminating one of the issues) and easing behavior. The tweenNumbers
will look like this:
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
}
No guarantee of desynching, though, but will normally work. Also a desynch (seeing previous line) can possibly happen if you have set stage framerate too high, so the video subsystem of a target device can't draw as many frames at once.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments