Learning ActionScript 3.0: Chapter 7, Motion
Pages: 1, 2, 3, 4, 5, 6, 7, 8

When these initializations are complete, it is safe to add the ball movie clip to the display list and, to round out the xmlLoaded() function, create another listener to react to the end of the animation. The listener's function, in lines 22 through 24, simply resets the name of a Play button, which we will discuss in the next code block.

14  function xmlLoaded(evt:Event):void {
15      var anim_xml:XML = XML(xml_loader.data);
16      anim = new Animator(anim_xml, ball);
17     ball.transform.colorTransform = anim.motion.keyframes[0].color;
18     addChild(ball);
19     anim.addEventListener(MotionEvent.MOTION_END, onMotionEnd,
       false, 0, true);
20  }
21
22  function onMotionEnd(evt:MotionEvent):void {
23      Button(getChildByName("Play")).label = "Play";
24  }

The following segment of ActionScript is responsible for creating all the buttons that will control the animation. The createController() function walks through a loop that creates as many buttons as are named in the array that is passed to it. Each time through the loop, an instance of the Button component is created and positioned, its width is adjusted, and its label and name are set to the string in the current index of the function array. Lastly, a mouse click listener is added to the array to trigger the function responsible for navigation, and the button is added to the display list. This process takes place five times, to match the five button names in the array passed to the function.

25  createController(["Play","Pause","Stop","Next Frame","Toggle
    Scale"]);
26
27  function createController(btns:Array):void {
28      for (var i:Number = 0; i<btns.length; i++) {
29          var btn:Button = new Button();
30          btn.x = 35 + i*100;
31          btn.y = 350;
32          btn.width = 80;
33          btn.label = btns[i];
34          btn.name = btns[i];
35          btn.addEventListener(MouseEvent.CLICK, onNav, false, 0,
            true);
36          addChild(btn);
37      }
38  }

The last function in the script handles all the navigation for the animation. When a button is clicked, the listener calls this function, passing information about the event and, by extension, the button itself. Based on the name of the button, one of five blocks in a switch statement executes, invoking methods from the Animator class, as well as other tasks. If you are unfamiliar with the switch statement, please consult Chapter 2 for more information.

The Play button first confirms that the animation is not already playing and, if it is not playing, checks to see whether it's paused. If so, it resumes playback and clears the isPaused flag. If not, it plays the animation from the beginning. The Pause button pauses the animation and sets the isPaused flag. It also switches the label of the Play button to reflect the animation's paused status. The Stop button stops and rewinds the animation, clears the isPaused flag, and sets the label of the Play button back to "Play." The last playback control simply advances the animation to its next frame.

39   function onNav(evt:MouseEvent):void {
40       switch (evt.target.name) {
41          case "Play" :
42              if (!anim.isPlaying) {
43                 if (isPaused) {
44                     anim.resume();
45                     isPaused = false;
46                 } else {
47                     anim.play();
48                 }
49             }
50             break;
51         case "Pause" :
52             anim.pause();
53             isPaused = true;
54             Button(getChildByName("Play")).label = "Resume";
55             break;
56         case "Stop" :
57             anim.stop();
58             anim.rewind();
59             isPaused = false;
60             Button(getChildByName("Play")).label = "Play";
61             break;
62         case "Next Frame" :
63             anim.nextFrame();
64             break;
65         case "Toggle Scale" :
66             var m:Matrix = anim.positionMatrix = new Matrix();
67             var s:Number;
68             if (isScaled) {
69                 s = 1;
70                 isScaled = false;
71             } else {
72                 s = .5;
73                 isScaled = true;
74             };
75             MatrixTransformer.setScaleX(m, s);
76             MatrixTransformer.setScaleY(m, s);
77             break;
78     }
79 }

The final button in the controller just begins to hint at some of the most interesting things you can do to the preexisting animations. The Animator class has a property called the positionMatrix that allows you to alter the animation as a whole. It can be shifted, scaled, rotated, and/or skewed without otherwise distorting its appearance. The final controller button toggles the animation between full- and half-scale, the paths of which are both visible in Figure 7-11. If the animation is already scaled, the Toggle Scale button will toggle the scale value between full- and half-size, and set the isScaled flag accordingly. Finally, the code uses the static MatrixTransformer class—which automatically adjusts a matrix for you to reflect your desired changes—invoking the setScaleX() and setScaleY() methods to scale the entire animation.


This excerpt is from Learning ActionScript 3.0. Learning ActionScript 3.0 gives you a solid foundation in the Flash language and demonstrates how you can use it for practical, everyday projects. The book does more than give you a handful of sample scripts, defining how ActionScript and Flash work. It gives you a clear look into essential topics such as logic, event handling, displaying content, migrating legacy projects to ActionScript 3.0, classes, and much more. Written for those new to the language, this book doesn't rely exclusively on prior knowledge of object-oriented programming (OOP). Instead, it helps you expand your skillset by first focusing on clear, concise examples in the timeline, evolving into OOP examples over time-allowing you to choose the programming approach with which you are most comfortable.

buy button

With the ability not only to control, but also to easily transform, a potentially complex timeline tween entirely through ActionScript, the Animator class has a lot of potential for both utility and creativity. Many animations can be lovingly crafted and tweaked in the timeline and can be played back anywhere through code, again and again—even swapped and loaded from external sources at runtime. Entire libraries of highly portable animations can be created and stored in efficient XML formats. Even if you entirely focus on ActionScript, the fl.motion package, in which both the Motion and Animator classes reside, may be worth a look.

Section 7.6: Particle Systems

Example
Figure 7-12: A particle system with a gravity setting of 2 and .2

Particle systems are a way of simulating complex objects or materials that are composed of many small particles, such as fluids, fireworks, explosions, fire, smoke, water, snow, and so on. Complex systems are achievable because individual particles are generated, each is given its own characteristics, and each behaves autonomously. Further, the particles themselves are typically easy to adjust, or even replace, making it possible to alter the appearance or functionality of the system relatively easily. These are also characteristics of object-oriented programming, so it's not surprising that particle systems are often written using this approach.

To end this chapter, we'd like to create a very simple particle system—using only two classes—which looks a little bit like a psychedelic water fountain. Color circles shoot up out of the "fountain" and then fall down under the effect of gravity. shows what the system looks like.

The entry point to the particle system is the document class ParticleDemo. After declaring variables to determine the point at which the particles will appear, all the class constructor does is add an enter frame event listener to the stage. Upon every enter frame event, the listener function creates a new instance of the Particle class, which creates a particle and adds it to the display list.

1  package {
2
3      import flash.display.Sprite;
4      import flash.events.Event
5
6      public class ParticleDemo extends Sprite {
7
8         private var emitterX:Number = stage.stageWidth/2;
9         private var emitterY:Number = stage.stageHeight/2;
10
11          public function ParticleDemo() {
12             stage.addEventListener(Event.ENTER_FRAME, onLoop,
            false, 0, true);
13         }
14
15         private function onLoop(evt:Event):void {
16             var p:Particle = new Particle(emitterX,
17                                           emitterY,
18                                         Math.random()*11 − 6,
19                                         Math.random()*−20,
20                                         1,
21                                         Math.random()*0xFFFFFF);
22             addChild(p);
23         }
24     }
25 }

Five parameters pass to each class when its particle is created. The first two are the x and y coordinates of the particle emitter which dictate the origin location for each new particle. The next two parameters are randomly chosen values for the x and y velocities. The first value is for the x velocity, and is between −5 and 5. That's because the range of numbers is 0 to 11, but subtracting 6 offsets the selected value. The y velocity is between 0 and −20, so particles start by moving up. Next are a gravity value of 1 and a random color for each particle in the range of black (0x000000) to white (0xFFFFFF).

To see how the particle generator works, look within the Particle class. The first 13 lines cover the required setup, including importing the display and geom packages, and the Event class from the events package. Also included are the declaration of the position, velocity, and gravity variables that are private to this class.

1 package {
2
3     import flash.display.*;
4     import flash.geom.*
5     import flash.events.Event;
6
7     public class Particle extends Sprite {
8
9         private var _xpos:Number;
10         private var _ypos:Number;
11         private var _xvel:Number;
12         private var _yvel:Number;
13         private var _grav:Number;

First, the class constructor populates the private variables with the parameters passed in from the document class described earlier. Next, it creates a particle from the Ball class in the library and adds it to the display list. The constructor then sets four values: the particle's x and y position, opacity, and x and y scale. The same range-plus-offset technique used for x velocity when creating the particle is also used here for scale. This allows a scale range up to 200 percent, but guarantees a minimum scale of 10 percent.

14          public function Particle(xp:Number, yp:Number, xvel:Number,
            yvel:Number, grav:Number, col:uint) {
15              _xpos = xp;
16              _ypos = yp;
17              _xvel = xvel
18              _yvel = yvel
19              _grav = grav;
20
21              var ball:Sprite = new Ball();
22              addChild(ball);
23
24              x = _xpos;
25              y = _ypos;
26              alpha = .8;
27              scaleX = scaleY = Math.random() * 1.9 + .1;
28
29              var colorInfo:ColorTransform = ball.transform.
                colorTransform;
30              colorInfo.color = uint(col);
31              ball.transform.colorTransform = colorInfo;
32
33              addEventListener(Event.ENTER_FRAME, onRun, false, 0,
                true);
34          }

Pages: 1, 2, 3, 4, 5, 6, 7, 8

Next Pagearrow