Automating the Process

All these sliders for rotation give you a lot of control, but what youve created is something like a piece of construction machinery with hydraulic levers to move around the parts . If you want to make something really walk, youre going to have to step back and give it some self-control.

You just need a way for each segment to smoothly swing back and forth, and then somehow synchronize them all. That sounds like a job for a sine wave.

In ch13_04.fla , Ive replaced the sliders with a trig function. It takes the sine of the cycle variable (which is initialized to 0), and multiplies it by 90, resulting in a value from 90 to ˆ 90. The cycle variable is constantly increased, so you get an oscillation. For now, Ive used the resulting angle variable to control both segments. I made update the handler for the enterFrame event so the motion is constant.

  var cycle:Number = 0;  update();  onEnterFrame = update;  function update():Void {  var angle:Number = Math.sin(cycle) * 90;   cycle += .05;  seg0._rotation =  angle  ;       seg1._rotation = seg0._rotation +  angle  ;       var radians:Number = seg0._rotation * Math.PI / 180;       seg1._x = seg0._x + Math.cos(radians) * 120;       seg1._y = seg0._y + Math.sin(radians) * 120; } 

Building a natural walk cycle

OK, now you have something moving around looking vaguely arm-like. Lets turn it into a leg. Start with the following changes:

  • Make the system point down, by adding 90 to seg0 s rotation and reducing its range of motion from 90 degrees in both directions to 45 degrees.

  • Use a separate angle for each segment, so youll have angle0 and angle1 .

  • Reduce angle1 s range to 45, and then add 45 to it. This makes its final range 0 to 90, so that it bends in only one direction, like a real knee. If that isnt totally clear, try it with and without the added 45 to see what its doing, and try some other numbers in there, until you get a feel for how it all fits together.

You end up with the following ( ch13_05.fla ):

 var cycle:Number = 0; update(); onEnterFrame = update; function update():Void {  var angle0:Number = Math.sin(cycle) * 45 + 90;   var angle1:Number = Math.sin(cycle) * 45 + 45;  cycle += .05;       seg0._rotation =  angle0  ;       seg1._rotation = seg0._rotation +  angle1  ;       var radians:Number = seg0._rotation * Math.PI / 180;       seg1._x = seg0._x + Math.cos(radians) * 120;       seg1._y = seg0._y + Math.sin(radians) * 120; } 

Well, youre getting there, as shown in Figure 13-4. This is starting to look like a leg, or at least starting to move like one.

image from book
Figure 13-4: The beginnings of a walk cycle

The problem is it doesnt really look like its walking. Maybe its kicking a half-hearted field goal, or perhaps practicing some ballet moves, but its not walking. Whats happening now is that both segments are moving in the same direction at the same time. They are totally in sync, which, if you were to analyze an actual walk cycle, is not how it works.

The segments are in sync because they are both using the cycle variable to calculate their angle. To throw them out of sync, you could resort to using cycle0 and cycle1 variables , but you dont need to go that far with it. Instead, you can just offset cycle a bit when using it to find angle1 , like so:

 var angle1:Number = Math.sin(cycle  + offset  ) * 45 + 45; 

Of course, youll need to define offset earlier in the code. But how much should offset be? I dont know that theres any set amount. Experiment until you find something that looks good. Ill give you a hint: It should be something between Math.PI and ˆ Math.PI (or 3.14 and ˆ 3.14). Anything more or less than that is just going to kind of double back on itself. For instance, I used ˆ Math.PI / 2 , which puts it a quarter of a cycle behind angle0 . Of course, -Math.PI / 2 is about ˆ 1.57, so you might want to try other numbers around that value, like ˆ 1.7 or -1.3, and see if that looks better or worse . A little later, Ill throw in a slider to do it all dynamically. The file with this offset in it is ch13_06.fla .

Now, this whole one leg walking thing sounds a bit too Zen for me, so lets add another leg. Youll start by throwing in two more segments, named seg2 and seg3 . The seg2 movie clip should be in the exact same position as seg0 , as it will also be the top level, or base, of the whole leg, but seg3 can be anywhere , as it will be positioned by code. Figure 13-5 shows the setup.

image from book
Figure 13-5: Clips seg0 and seg2 appear as one, and seg1 and seg3 are below.

Now, rather than duplicate all the code that makes seg0 and seg1 walk, I abstracted it into its own function, called walk :

 function walk(segA:MovieClip, segB:MovieClip, cyc:Number) {       var angleA:Number = Math.sin(cyc) * 45 + 90;       var angleB:Number = Math.sin(cyc + offset) * 45 + 45;       segA._rotation = angleA;       segB._rotation = segA._rotation + angleB;       var radians:Number = segA._rotation * Math.PI / 180;        segB._x = segA._x + Math.cos(radians) * 120;       segB._y = segA._y + Math.sin(radians) * 120; } 

Notice that the function takes three parameters: two movie clips, segA and segB , which are the two segments, and cyc , which stands for cycle . The rest of the code is pretty much what youve been using. Now, to make seg0 and seg1 walk, just call it like this:

 walk(seg0, seg1, cycle); 

By now, you see where Im going with this, and youre ready to make seg2 and seg3 walk as well. If you jump right into it, youll end up with this as your update function:

 function update():Void {       walk(seg0, seg1, cycle);       walk(seg2, seg3, cycle);       cycle += .05; } 

But if you try that, youre going to be wondering where the second leg is. The problem is that both legs are moving exactly in sync, so they appear as one. Once again, you need to desynchronize. Last time, you offset the bottom segments position on the cycle from the top segments position. This time, youll offset the second leg from the first. Again, this comes down to changing the value its using for cycle . And once again, rather than keeping track of two different variables, just add something to or subtract something from cycle before you send it into the walk function. So the update function becomes this:

 function update():Void {       walk(seg0, seg1, cycle);       walk(seg2, seg3, cycle  + Math.PI  );       cycle += .05; } 

Why Math.PI ? The long answer is that value puts the second leg 180 degrees out of sync with the first, so the first leg will move forward while the second is moving back, and vice versa. The short answer is because it works! You can try it out with some different values, say Math.PI / 2 , and see that it looks a lot more like a gallop than a walk or run. But keep that in mindyou may need to make something gallop someday!

The file as it stands is available as ch13_07.fla and looks like Figure 13-6. In the next version, you're going to make a lot of things dynamic with sliders, but I highly recommend that you play around with some of these variables now manually, by changing the values in the code and seeing how the values affect things.

image from book
Figure 13-6: Behold! It walks!

Making it dynamic

Next, lets really play around with this walk cycle and see just how much you can change it by altering the various values that go into it. The ch13_08.fla file has a slider component in it that you can use for this project (or anything else you might need a slider for). You simply put it on stage and set the minimum, maximum, and initial values of the slider. Dont forget to name the instance. After that, you can read the current setting of the slider with its value property.

For the next example, I set up five of these sliders across the top of the stage, as shown in Figure 13-7.

image from book
Figure 13-7: Adding the sliders

Table 13-1 shows the slider instance names (from left to right), what they do, and the settings to use for them. These are just ranges and values I found to work well. By all means, feel free to experiment with other values.

Table 13-1: The Sliders for Controlling the Walk Cycle

Instance

Description

Settings

speedSlider

Controls the speed at which the system moves.

maximum: 0.3,

minimum: 0,

value: 0.12

thighRangeSlider

Controls how far back and forth the top-level segments (thighs) can move.

maximum: 90,

minimum: 0,

value: 45

thighBaseSlider

Controls the base angle of the top-level segments. So far, this has been 90, meaning that the legs will point straight down, and move back and forth from there. But you can get some interesting effects by changing this value.

maximum: 0,

minimum: 180,

value: 90

calfRangeSlider

Controls how much range of motion the lower segments (calves) have.

maximum: 90,

minimum: 0,

value: 45

calfOffsetSlider

Controls the offset value (youve been using ˆ Math.PI / 2 ).

maximum: ˆ 3.14,

minimum: 3.14,

value: ˆ 1.57

Now, you need to go in and change the code so that it uses the values provided by the sliders, rather than hard-coded values.

 var cycle:Number = 0; update(); onEnterFrame = update; function update():Void {       walk(seg0, seg1, cycle);       walk(seg2, seg3, cycle + Math.PI);       cycle +=  speedSlider.value  ; } function walk(segA:MovieClip, segB:MovieClip, cyc:Number) {       var angleA:Number = Math.sin(cyc) *  thighRangeSlider.value   + thighBaseSlider.value  ;       var angleB:Number = Math.sin(cyc +  calfOffsetSlider.value  )                   *  calfRangeSlider.value  +  calfRangeSlider.value  ;       segA._rotation = angleA;       segB._rotation = segA._rotation + angleB;       var radians:Number = segA._rotation * Math.PI / 180;       segB._x = segA._x + Math.cos(radians) * 120;       segB._y = segA._y + Math.sin(radians) * 120; } 

This code is exactly as it was before, but now its using the slider values rather than values hard-coded into the file. Im sure you can have a lot of fun with this file, exploring different variations of the walk cycle.



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