Recipe 11.6. Using Trigonometry


Problem

You want to do some advanced animation, involving rotation, circular motion, or oscillation.

Solution

Use the built-in math functions Math.sin( ), Math.cos( ), and Math.atan2( ).

Discussion

Recipes 11.2 and 11.4 touched on the use of the sine and cosine functions, but they can be used for many other useful effects, such as moving objects in circular or oval paths, smoothly back and forth around a position, or rotating to a particular angle. Both Math.sin( ) and Math.cos( ) are based on the properties of a right triangle (a triangle that has one 90-degree angle). Without getting into a trigonometry lesson, if you feed either function a series of increasing numbers, they will return values that go smoothly back and forth from -1 to 0, 1, 0, and back to -1, continuously. The following code snippet demonstrates this:

for(var i:Number = 0; i < 10; i += 0.1) {     trace(Math.sin(i)); }

This traces a long list of numbers. If you examine those numbers, you'll see that they start at 0, go up to 0.999, back down to -0.999, back up, and so on. You can now multiply that by another number, say 40, and get a list of values from -40 to 40. If you use this in an enterFrame handler, or timer-based method, and apply the result to an object's position, you can get it to oscillate back and forth, or up and down, as the following example shows:

package {     import flash.display.Sprite;     import flash.events.Event;          public class Oscillation extends Sprite {         private var _sprite:Sprite;         private var _angle:Number = 0;         private var _radius:Number = 100;                  public function AS3CB(  ) {             _sprite = new Sprite(  );             _sprite.graphics.beginFill(0x0000ff, 100);             _sprite.graphics.drawCircle(0, 0, 25);             _sprite.graphics.endFill(  );             _sprite.x = 0;             _sprite.y = 100;             addChild(_sprite);             addEventListener(Event.ENTER_FRAME, onEnterFrame);         }                  public function onEnterFrame(event:Event):void {             _sprite.x = 200 + Math.sin(_angle) * _radius;             _angle += .05;         }     }     }

Here, _angle is the variable holding the increasing value fed to Math.sin( ). The result is multiplied by the _radius variable, which is set at 100. This causes the sprite to go back and forth 100 pixels.

If you use Math.cos( ) and do the same thing with the sprite's y position, you have circular motion:

public function onEnterFrame(event:Event):void {     _sprite.x = 200 + Math.sin(_angle) * _radius;     _sprite.y = 200 + Math.cos(_angle) * _radius;     _angle += .05; }

To make more of an oval shaped path, just use a different radius value on each axis. For example, set _xRadius to 100, _yRadius to 50, and do the following:

public function onEnterFrame(event:Event):void {     _sprite.x = 200 + Math.sin(_angle) * _xRadius;     _sprite.y = 200 + Math.cos(_angle) * _yRadius;     _angle += .05; }

Now, if you create separate angles and amounts to add to each angle, you can get a very random-looking motion. First, create separate variables for each axes' factors:

private var _xAngle:Number = 0; private var _yAngle:Number = 0; private var _xSpeed:Number = .13; private var _ySpeed:Number = .09; private var _xRadius:Number = 100; private var _yRadius:Number = 50;

Then apply those to the motion code:

public function onEnterFrame(event:Event):void {     _sprite.x = 200 + Math.sin(_xAngle) * _xRadius;     _sprite.y = 200 + Math.cos(_yAngle) * _yRadius;     _xAngle += _xSpeed;     _yAngle += _ySpeed; }

One possible use for this example is to simulate a fly, randomly buzzing around a room.

Another very useful trig function is Math.atan2( ). The main use for this is in finding the angle between two points. It takes two parameters: the distance between the two points on the y-axis, and the distance between them on the x-axis. It then returns the angle, in radians, between the points.

A common scenario for using Math.atan2( ) is in making an object (a sprite, for example) point at the mouse. The y distance is mouseY _sprite.y, and the x distance is mouseX _sprite.x. Math.atan2( ) returns an angle. Convert that to degrees and use it to set _sprite.rotation. Of course, you'll need some sort of sprite graphic that shows which direction it is rotating. The next example creates the classic "following eyes," a little desktop toy that follows the mouse around the screen and has been created for just about every graphical operating system out there (actually, this example creates only a single eye, but it demonstrates the principle):

package {     import flash.display.Sprite;     import flash.events.Event;          public class FollowingEye extends Sprite {         private var _sprite:Sprite;                  public function AS3CB(  ) {             _sprite = new Sprite(  );             _sprite.graphics.beginFill(0xffffff, 100);             _sprite.graphics.drawCircle(0, 0, 25);             _sprite.graphics.endFill(  );             _sprite.graphics.beginFill(0x000000, 100);             _sprite.graphics.drawCircle(20, 0, 5);             _sprite.graphics.endFill(  );             _sprite.x = 100;             _sprite.y = 100;             addChild(_sprite);             addEventListener(Event.ENTER_FRAME, onEnterFrame);         }                  public function onEnterFrame(event:Event):void {             var dx:Number = mouseX - _sprite.x;             var dy:Number = mouseY - _sprite.y;             var radians:Number = Math.atan2(dy, dx);             _sprite.rotation = radians * 180 / Math.PI;         }     }     }

The setup code draws an extra circle on the right edge of the first. When you are doing this kind of rotation, align your graphics so that "zero degrees" is facing to the right like this. The enterFrame handler calculates the two distances and the resulting angle, converts to degrees and assigns it to the eye's rotation.




ActionScript 3. 0 Cookbook
ActionScript 3.0 Cookbook: Solutions for Flash Platform and Flex Application Developers
ISBN: 0596526954
EAN: 2147483647
Year: 2007
Pages: 351

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