Friction

So far, youve seen two scenarios:

  • The object is simply moving with whatever velocity it has until it hits a boundary.

  • Either the object itself or some external force is applying some acceleration to the object, changing its velocity.

With either setup, unless the object is being pushed or pulled, or it hits something, it will keep going in the same direction at the exact same speed. But in the real world, it doesnt happen just like that.

Heres an example. Grab a piece of paper, crumple it up very loosely, and throw it as hard as you can. Theres a good chance it didnt even make it across the room. Sure, gravity was pulling it down (y axis), but when it left your hand, it was moving pretty fast on the x axis. Yet, very quickly, it had almost zero x velocity.

Obviously, no negative acceleration was pulling the paper back towards your hand, yet, its velocity was changed. This is known as friction , drag , resistance , or damping . Although its not technically a force, it does kind of act that way, in that it changes an objects velocity. The rule is that friction reduces only the magnitude of the velocity. Whichever direction the object is headed in, this will not be changed by friction. In other words, friction can reduce velocity to zero, but it will never make an object turn around and go in the other direction.

So, how do you implement friction in code? It turns out there are two ways. Like most things in life, you have the right way and the easy way. But unlike your parents, Im going to recommend the easy way. Even so, Im going to show you both ways, starting with the right one, and let you make up your own mind.

Friction, the right way

Friction is actually subtractive of velocity, which is to say you have a certain value for friction, and you subtract that from your velocity. Actually, you need to subtract it from the magnitude, or speed, of the velocity. You cant just subtract the friction from the x axis and y axis separately. If you do that for an object traveling at an angle, one of the component velocities will reach zero before the other, and the object will continue on for a while either vertically or horizontally, which will look pretty strange .

So, what you need to do is find the angular velocity in terms of speed and direction (if you dont have it already). To find the speed, you take the square root of vx squared plus vy squared (yes, thats the Pythagorean Theorem, which you should recognize from Chapter 3). To find the angle, you calculate Math.atan2(vy, vx) , which looks like this in code:

 var speed:Number = Math.sqrt(vx * vx + vy * vy); var angle:Number = Math.atan2(vy, vx); 

Then you can subtract the friction from the speed. But you want to make sure you dont send the speed into negative values, which would reverse the velocity. So, if your friction is greater than your speed, the speed just becomes zero. Here is the code for that calculation:

 if(speed > friction) {    speed -= friction; } else {    speed = 0; } 

At that point, you need to convert the angular velocity back into vx and vy , sine and cosine, like so:

 vx = Math.cos(angle) * speed; vy = Math.sin(angle) * speed; 

Quite a bit of work, eh? Heres how it looks all together ( ch06_06.fla ):

 init(); function init() {       friction = 0.1;       ball = attachMovie("ball", "ball", 0);       ball._x = Stage.width / 2;       ball._y = Stage.height / 2;       vx = Math.random() * 10 - 5;       vy = Math.random() * 10 - 5; } function onEnterFrame(Void):Void {       var speed:Number = Math.sqrt(vx * vx + vy * vy);       var angle:Number = Math.atan2(vy, vx);       if (speed > friction)       {           speed -= friction;       }       else       {           speed = 0;       }       vx = Math.cos(angle) * speed;       vy = Math.sin(angle) * speed;       ball._x += vx;       ball._y += vy; } 

Here, Ive given you a scaled-back velocity code. The friction is set to 0.1 , and the ball is given a random velocity on the x and y axes. In the onEnterFrame method, speed and angle are calculated as I just described. If speed is less than friction , subtract; otherwise , speed equals zero. Finally, vx and vy are recalculated and added to the position.

Go ahead and test this example several times to see it at different speeds and angles. Thats how friction looks. It took a dozen lines of code and four trig functions to accomplish. You could probably come up with a more optimized version, but all those calculations will be in there, one way or the other. I think youll agree that its time to look at the easy way.

Friction, the easy way

As you would expect, the easy way to do friction is not as accurate as the technique I just described, but I bet nobody will ever notice. It consists of two lines of simple multiplication. All you need to do is multiply the x and y velocities by some fraction of 1. A number like 0.9 or 0.8 usually works quite well. So, on each frame, the vx and vy become 80% or 90% of what they were last time. In theory, the velocity will approach zero, but never actually reach it. In practice, the computer can calculate such minute numbers only so far, and eventually its going to round down to zero velocity. But long before that, the motion will be so small it will be indiscernible.

The good news is that the velocity is never going to go negative with this method, so you dont have to worry about checking for that. Also, the x and y velocities will approach zero at the same rate, so theres no need to convert axis velocities to angular and back.

Heres the easy method in code ( ch06_07.fla ):

 init(); function init() {  friction = 0.9;  ball = attachMovie("ball", "ball", 0);       ball._x = Stage.width / 2;       ball._y = Stage.height / 2;       vx = Math.random() * 10 - 5;       vy = Math.random() * 10 - 5; } function onEnterFrame(Void):Void {  vx *= friction;   vy *= friction;  ball._x += vx;       ball._y += vy; } 

Now, thats certainly easier! Test this version a number of times and get a feel for it. Can you see the difference in motion between this and the correct method? Probably you can, because youve just seen them side by side. To the average viewer though, this one will look pretty realistic.

Friction applied

Now, lets return to our familiar spaceship and apply some friction to that universe. Its quite a different feel for just three additional lines of code. Heres the code ( ch06_08.fla ):

 init(); function init() {  friction = 0.97;  vr = 5;       thrust = 0.2;       vx = 0;       vy = 0;       left = 0;       right = Stage.width;       top = 0;       bottom = Stage.height;       ship = attachMovie("ship", "ship", 0);       ship._x = Stage.width / 2;       ship._y = Stage.height / 2; } function onEnterFrame(Void):Void {       if (Key.isDown(Key.LEFT))       {             ship._rotation -= vr;       }       else if (Key.isDown(Key.RIGHT))       {             ship._rotation += vr;       }       if (Key.isDown(Key.UP))       {             var radians:Number = ship._rotation * Math.PI / 180;             var ax:Number = Math.cos(radians) * thrust;             var ay:Number = Math.sin(radians) * thrust;             vx += ax;             vy += ay;             ship.gotoAndStop(2);       }       else       {             ship.gotoAndStop(1);       }  vx *= friction;   vy *= friction;  ship._x += vx;       ship._y += vy;       if (ship._x - ship._width / 2 > right)       {             ship._x = left - ship._width / 2;       }       else if (ship._x + ship._width / 2 < left)       {             ship._x = right + ship._width / 2;       }       if (ship._y - ship._height / 2 > bottom)       {             ship._y = top - ship._height / 2;       }       else if (ship._y < top - ship._height / 2)       {             ship._y = bottom + ship._height / 2;       } } 

Dont forget to think outside the x, y box. Friction can be applied anywhere you have any type of velocity. Say you have something rotating (with a vr ). Applying friction to that will eventually cause it to slow down and stop spinning. Heres a quick example of applying friction to a spinning arrow movie clip ( ch06_09.fla ):

 var vr:Number = Math.random() * 100 - 50; var friction:Number = 0.95; function onEnterFrame():Void {       vr *= friction;       arrow._rotation += vr; } 

This is a very simple file, with the movie clip placed on stage manually and the code right on the timeline.

You can see how you could use this approach for all types of objects, such as a roulette wheel, an electric fan, or a propeller.



Foundation ActionScript. Animation. Making Things Move
Foundation Actionscript 3.0 Animation: Making Things Move!
ISBN: 1590597915
EAN: 2147483647
Year: 2005
Pages: 137
Authors: Keith Peters

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net