A Flash Developer Resource Site

Results 1 to 15 of 15

Thread: smoothness

  1. #1
    Senior Member
    Join Date
    Jul 2000
    Posts
    263

    smoothness

    Hey guys,
    How is it that sometimes designers can get the animations to be so freakin smooth. And Im not talking about only smooth on the fastest computers. Somehow they manage to make it their animations run very fluid. Any idea how to do this. I make all of my movies at 30 fps yet i dont seem to get the same kind of movement. Anyhelp would be great.
    Thanks
    Don
    http://www.stillloading.com
    http://www.threecell.com

  2. #2
    Senior Member jbum's Avatar
    Join Date
    Feb 2004
    Location
    Los Angeles
    Posts
    2,920
    Upload a simple example of something you made that isn't smooth enough.

    In general, most of the actionscript based animations I've seen posted on this board tend to use 1 of 4 different styles of movement.

    1. Linear movement. This is by far the most common by newbies (cause it's easy to do) and it looks the the jerkiest. Especially when starting and stopping.

    _x += k;

    (where k is a fixed number).

    2. Fractional ease-out. This starts fast but ends up smooth & slow. Often used for alpha fades and slides.

    _x += (target-_x)/k;

    3. Time-based Ease-in/Ease-out. This starts slow, speeds up and then slows down at the end. A personal favorite of mine, see below.

    k = elapsedTime/duration; // k = 0-1
    k = k*k*(3-2*k); // apply easing
    _x = start + (target - start)*k;

    4. Sine wave motion. This performs smooth oscillations or pendulum motions, another favorite of mine.

    _x = midPoint + Math.sin(timeValue) * width;



    #2 above, is VERY popular on this board. And you'll see numerous examples of it every day.

    It suffers from a few problems, which is why I like #3 better.

    a. When used to travel a large distance, such as to alpha fade from 0 to 255, it tends to be either fast and choppy or smooth and slow. It's hard to make it fast and smooth. If you plot subsequent values in a program like Excel, you'll see why - small values of K make big jumps at the beginning, and large values of K take a long time to converge.

    b. You can't easily predict how long it will take. Increasing K makes it slower, but how much?

    c. It's duration is proportional to framerate. Double the framerate, and it's twice as fast. You may like this, but I don't.

    d. It never actually reaches the target value - so to get it to stop, you have to add a test to see if it's close to the target value:

    dx = (target - _x);
    if (Math.abs(dx) < AcceptableMinimum)
    {
    // stop it
    }
    else
    _x += dx/k;


    This is why I prefer method #3. It starts smooth, ends smooth and takes a predictable amount of time, which you can specify in seconds or milliseconds. If you look at my prior posts, you'll see two or three examples of alpha and x tweens that use it.

    - Jim
    Last edited by jbum; 03-24-2004 at 07:20 PM.

  3. #3
    Senior Member
    Join Date
    Jul 2000
    Posts
    263
    Good lord,
    that was easily the most thorough response I could have ever imagined. Thank you very much. I will study these animation tactics.
    Sincerely,
    Don Ho
    http://www.stillloading.com
    http://www.threecell.com

  4. #4
    Banned NTD's Avatar
    Join Date
    Feb 2004
    Posts
    3,438
    Excellent info once again Jim!

    Regards
    NTD
    Last edited by NTD; 03-25-2004 at 07:11 PM.

  5. #5
    Senior Member
    Join Date
    Jul 2000
    Posts
    263

    clarificaiton

    Hey Jbum

    I have a question about number 3:
    k = elapsedTime/duration; // k = 0-1
    k = k*k*(3-2*k); // apply easing
    _x = start + (target - start)*k;

    where did the number 3-2 come from. Are they arbitrary? In addition, what is value of elapsedtime and duration. Do you just make it up. Are there certain numbers that typically make up these variables.
    Thanks
    Don
    http://www.stillloading.com
    http://www.threecell.com

  6. #6
    Senior Member jbum's Avatar
    Join Date
    Feb 2004
    Location
    Los Angeles
    Posts
    2,920
    k=k*k*(3-2*k)

    is a reduction of a common easing equation which I'll look up when I'm near my library (I think I got it out of Foley/Van Damn). It makes the numbers below .5 get smaller and the numbers above .5 get larger. Although I don't recommend futzing with the 3 and the 2, you can apply it twice if you want extra easing.

    k=k*k*(3-2*k)
    k=k*k*(3-2*k)

    It is instructive to see what these equations do in a spreadsheet like Excel.

    In one colum enter values going from 0 to 1:

    0
    .05
    .1
    .15
    .2
    .25
    .3
    etc...

    And the next colum over enter the formula:

    A1*A1*(3-2*A1)

    Then select both columns and make a graph so you can see what the numbers do. The left colum makes a straight line (this is why its called linear motion) and the right column makes an S shaped curve.

    Here's a complete example that shows how I get elapsedTime and duration. It assumes the existence of a movieclip called 'mc' and applies easing to the _xscale and _yscale to make a button expand and contract. FLA attached, which uses 24 fps.

    Code:
    MovieClip.prototype.doTween = function() {
    	// get elapsed time in milliseconds
    	var elapsedTime = getTimer()-this.startTime;
    	// convert to easing ratio 0-1
    	var k = elapsedTime/this.duration;
    	if (k>1) {
    		// are we done yet?
    		k = 1;
    		this.onEnterFrame = undefined;
    	}
    	// apply easing
    	k = k*k*(3-2*k);
    	// apply easing
    	// perform the tween
    	this._xscale = this._yscale=this.startS+(this.deltaS*k);
    };
    MovieClip.prototype.startTween = function(targetScale, seconds) {
    	// get start time, in milliseconds
    	this.startTime = getTimer();
    	// compute duration in milliseconds
    	this.duration = seconds*1000;
    	// get start and end values
    	this.startS = this._xscale;
    	this.targetS = targetScale;
    	// compute the difference (the 'delta')
    	this.deltaS = this.targetS-this.startS;
    	// begin tweening
    	this.onEnterFrame = this.doTween;
    };
    mc.onRollOver = function() {
    	// expand to 150% over 1.5 seconds
    	this.startTween(150, 1.5);
    };
    mc.onRollOut = function() {
    	// contract to 100% over 0.5 seconds
    	this.startTween(100, 0.5);
    };
    Attached Files Attached Files

  7. #7
    Senior Member jbum's Avatar
    Join Date
    Feb 2004
    Location
    Los Angeles
    Posts
    2,920
    One more cool tween to add to this thread, so I can point people to it for future reference.

    A spring-effect in which the button is scaled with a spring-like motion. Here's the script:

    Code:
    onClipEvent (load) {
    	this.speed = 0;   // current tween velocity
    	this.tScale = 100; // target scale
    	this.stiffness = .3;
    	// (from 0-1 or so) spring stiffness - large numbers make the spring 'stiffer'
    	this.damping = .8;
    	// (from 0-1) affects rate of decay - lower numbers make spring settle faster
    }
    
    // spring animation code
    onClipEvent (enterFrame) {
    	var ds = this.tScale - this._xscale;
    	this.speed  += ds*this.stiffness;
    	this.speed *= this.damping;
    	this._xscale += this.speed;
    	this._yscale += this.speed;
    }
    
    // we set the desired xcales/yscale here
    on (rollOver) {
    	this.tScale = 120;
    }
    on (rollOut) {
    	this.tScale = 100;
    }
    And a sample FLA file demonstrating the effect is enclosed.
    Attached Files Attached Files

  8. #8
    still learnin'
    Join Date
    Oct 2002
    Location
    la la land
    Posts
    71
    sorry to dig this thread up but i've attempted to adapt jbum's code to take in any movieclip property like so =>

    code:

    //this is on frame 1
    MovieClip.prototype.doTween = function() {
    // get elapsed time in milliseconds
    var elapsedTime = getTimer()-this.startTime;
    // convert to easing ratio 0-1
    var k = elapsedTime/this.duration;
    if (k>1) {
    // are we done yet?
    k = 1;
    delete this.onEnterFrame;
    if(this.func){func();}
    }
    // apply easing
    k = k*k*(3-2*k);
    // apply easing
    // perform the tween
    this[this.prop]= this.startS+(this.deltaS*k);
    trace(this[this.prop]);
    };
    MovieClip.prototype.startTween = function(targProp, targ, seconds, func) {
    // get start time, in milliseconds
    this.startTime = getTimer();
    // compute duration in milliseconds
    this.duration = seconds*1000;
    //store reference to func
    if(typeof func == "function" && func != null && func != undefined){
    this.func = func;
    }
    //store _property to change
    this.prop = targProp;
    // get start and end values
    this.startS = this[targProp];
    this.targ = targ;
    // compute the difference (the 'delta')
    this.deltaS = this.targetS-this.startS;
    // begin tweening
    this.onEnterFrame = this.doTween;
    };
    oval_mc._alpha = 30;

    //this is on frame 2
    oval_mc.startTween('_alpha', 100, 1.5, undefined);
    stop();



    the thing is, nothing happens...the _alpha property remains at 0.

    i've tried with other properties as well and the results are the same

    Rich Media Developer
    Full Time Poser
    Really Complex and Pretentious Acronym for Higher Learnin' (MBA, WTF, OMG, PHD)
    www.unconsciouscollektiv.com

  9. #9
    Senior Member
    Join Date
    Jul 2002
    Location
    Slovenia
    Posts
    193
    Well, when I want to create an easing function, I just use what we have learnt during the math classes.

    Since speed is the first derivative of the distance traveled against time, you may "invent" speed functions by looking at the integral of a random function you like most. A quadratic equation is quite good for that, a sine function can also be used (you can use whatever you want). Just integrate, select the interval you like most (the interval is time), and induce a parameter that generates an area (under the speed curve) that suits your distance.

    An example of derivation of a quadratic function:
    Code:
    Lets say we want the movie to move in a time interval of 40 frames (i.e. timeinterval=40):
    speed = a(- t^2 + (timeinterval/2)^2)
    Integrate the speed function against t (lower bound is -(timeinterval/2) and the upper is timeinterval/2):
    distance = a(-((timeinterval/2)^3)/3+(timeinterval/2)^2×timeinterval/2)-
    a(-((-timeinterval/2)^3)/3+(timeinterval/2)^2×-timeinterval/2)
    If you simplify this, you get:
    distance = (a×timeinterval^3)/6
    But you know the distance - say distance is 500 (pixels), and can now calculate the value of parameter a:
    a = distance×6/timeinterval^3
    Now we have a function of speed:
    speed = distance × 6 / timeinterval^3(-t^2 + (timeinterval/2)^2)
    That's the derivation of an example function. If you don't see the power of this method... well here we go:
    1. you may create functions that dont ease only in a linear direction, but may change the direction of movement according to any function (say speed becomes negative, or jups up a luttle and then back down...)
    2. you may produce virtually any easing function
    3. you may practice your math and discover not to create speed functions but displacement functions - which are faster and more accurate - they do not involve intergration (rather trivial actually)
    The disadvantages of the method:
    1. inaccurate

    Here's an example of the derived function...
    Attached Files Attached Files

  10. #10
    Senior Member Bobby Hill's Avatar
    Join Date
    Feb 2004
    Posts
    243
    Is it possible to apply script 2 to the main timeline or does it have to be applied to a movieclip only?

    Thanks,
    "My boss sits and watches TV in a hot dog suit and I think he might be a moron."

  11. #11
    Senior Member jbum's Avatar
    Join Date
    Feb 2004
    Location
    Los Angeles
    Posts
    2,920
    I think you're asking if you can use it on a script which is on the main timeline. Yes you can. Let's say there is a movieclip called 'mc'. Here is a more fleshed out version of that script.

    code:

    mc.target = 200;
    mc.speed = 2;

    mc.onEnterFrame = function()
    {
    var dx = this.target - this._x;
    if (Math.round(dx) == 0)
    {
    this._x = this.target;
    delete this.onEnterFrame;
    }
    else {
    this._x += dx / this.speed;
    }
    }


  12. #12
    Senior Member Bobby Hill's Avatar
    Join Date
    Feb 2004
    Posts
    243
    I guess I did not explain what I am trying to do well enough. If I have animation on the main timeline with no movieclips, can I still apply script 2 to the main timeline?
    "My boss sits and watches TV in a hot dog suit and I think he might be a moron."

  13. #13
    Senior Member
    Join Date
    Nov 2001
    Posts
    1,145
    movieclip only, the scripting has to be able to identify what it is acting on - an object, you have to turn something into an object before you can use scripting on it (in general).

    for example if you're gonna move a start 200 to the right how do you plan on identifying the star in the programming if it's just a shape that you drew?

  14. #14
    Senior Member Bobby Hill's Avatar
    Join Date
    Feb 2004
    Posts
    243
    Originally from Jbum

    Upload a simple example of something you made that isn't smooth enough.

    In general, most of the actionscript based animations I've seen posted on this board tend to use 1 of 4 different styles of movement.

    1. Linear movement. This is by far the most common by newbies (cause it's easy to do) and it looks the the jerkiest. Especially when starting and stopping.

    _x += k;

    (where k is a fixed number).
    I am trying to create a smooth linear animation; and, I was wondering if the linear equation would be smooth instead of jerky or did I misunderstand Jbum's statement.

    Thanks,
    "My boss sits and watches TV in a hot dog suit and I think he might be a moron."

  15. #15
    Member
    Join Date
    Nov 2003
    Posts
    88
    what if I wanted this MC to move at a steady pace,
    then once it reached its destination ..
    maybe faded out? .. or start back at the begining?
    is that possible?

    thanks,
    -dan

    Quote Originally Posted by jbum
    I think you're asking if you can use it on a script which is on the main timeline. Yes you can. Let's say there is a movieclip called 'mc'. Here is a more fleshed out version of that script.

    code:

    mc.target = 200;
    mc.speed = 2;

    mc.onEnterFrame = function()
    {
    var dx = this.target - this._x;
    if (Math.round(dx) == 0)
    {
    this._x = this.target;
    delete this.onEnterFrame;
    }
    else {
    this._x += dx / this.speed;
    }
    }


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center