Springs

The other kind of particle attraction you probably want to try is springs. Yes, springs, my favorite subject! Recall that in Chapter 8, you tried out chains of springs and objects springing to each other. Here, youll look at a broader application, where you have many particles, all springing to each other, as in the gravity examples you just saw.

The inspiration for this example came from a piece Jared Tarbell did at www.levitated.net, called The Node Garden, shown in Figure 12-4. The idea is that you could have a field of these nodes (particles), and they could each have various types of interactions with any other nodes that were nearby. I think it was my idea to have one of those reactions be a spring.

image from book
Figure 12-4: Jared Tarbells Node Garden

Gravity vs. springs

If you look at gravity and springs, you see they are very similar, yet almost exactly opposite . Both apply acceleration to two objects to pull them together. But in gravity, the farther apart the objects are, the less acceleration there is. In a spring, the acceleration gets larger as the distance increases .

So, while you could just swap out the gravity code and plug the spring code into the previous examples, the effect might not be too interesting, because the particles would eventually just lump into a mass. Springs cant tolerate distance. If gravitys motto is out of sight, out of mind, a springs credo is absence makes the spring grow fonder.

So you have a dilemma. You want to have particles attract with a spring force, but you want them to tolerate some distance and not be pulling themselves together. My solution for this was to come up with a minimum distance variable. Mathematically speaking, it might be more like a maximum distance, because it is the largest distance at which a reaction will still take place. But minimum distance always seemed right to my brain, because it means that particles must be at least this close together to react . If they are farther apart, they ignore each other.

A springy node garden

Lets get started making our own springy node garden. First, you need a node symbol. Im going out on a limb here and using a whole new graphic theme! First, I changed the background of the movie to black. Then I took the particle movie clip and changed the graphic in it to a 10-pixel-diameter circle with a centered gradient fill. The center of the fill is pure white, 100 percent opaque . The outer edge of the fill is black, 0% alpha. The result is a kind of small, glowing orb, as you can see in Figure 12-5. Thats how I picture a node. You can make your own, or use what I came up with in ch12_05.fla .

image from book
Figure 12-5: My version of a node

Now, onto the code. First, set some variables for number of particles, the minimum distance I just talked about, and a spring value.

 var numParticles:Number = 30; var minDist:Number = 100; var springAmount:Number = .001; 

In the earlier spring examples in Chapter 8, you used something like 0.2 for a spring amount. You need to use something much lower here, as a lot more particles are interacting. If you go too high, the velocity will build up much too fast. However, if you go too low, the particles will just meander about the screen, seemingly unaware of each other.

Then initialize things:

 init(); function init():Void {       for(var i:Number=0;i<numParticles;i++)       {             var particle:MovieClip = attachMovie("particle",                                                  "p" + i, i);             particle._x = Math.random() * Stage.width;             particle._y = Math.random() * Stage.height;             particle.vx = Math.random() * 6 - 3;             particle.vy = Math.random() * 6 - 3;       } } 

This just creates a bunch of particles, throws them around the screen, and gives them random velocities. Note that I got rid of mass for this example. Later, in the Node with mass section, Ill show you an experiment with adding mass back in.

Next comes the onEnterFrame action function:

 function onEnterFrame():Void {       for(var i:Number = 0;i<numParticles;i++)       {             var particle:MovieClip = this["p" + i];             particle._x += particle.vx;             particle._y += particle.vy;  if(particle._x > Stage.width)   {   particle._x = 0;   }   else if(particle._x < 0)   {   particle._x = Stage.width;   }   if(particle._y > Stage.height)   {   particle._y = 0;   }   else if(particle._y < 0)   {   particle._y = Stage.height;   }  }       for(i=0;i<numParticles-1;i++)       {             var partA:MovieClip = this["p" + i];             for(var j:Number = i+1;j<numParticles;j++)             {                   var partB:MovieClip = this["p" + j];  spring(partA, partB);  }       } } 

This should look pretty familiar. Its basically the same as the gravity setup. I just added in screen wrapping and called a spring function instead of gravitate .

Now to the meat of it, the spring function itself:

 function spring(partA:MovieClip, partB:MovieClip):Void {       var dx:Number = partB._x - partA._x;       var dy:Number = partB._y - partA._y;       var dist:Number = Math.sqrt(dx*dx + dy*dy);       if(dist < minDist)       {             var ax:Number = dx * springAmount;             var ay:Number = dy * springAmount;             partA.vx += ax;             partA.vy += ay;             partB.vx -= ax;             partB.vy -= ay;       } } 

First, you find the distance between the two particles. If its not less than minDist , you move on. If it is less, however, you figure out the acceleration on each axis, based on the distance and springValue . You add that acceleration to partA s velocity and subtract it from partB s velocity. This pulls the particles together.

Go ahead and try it out. Youll see something like Figure 12-6. Notice how the particles kind of clump together like flies buzzing around a . . . whatever flies like to buzz around. But even those clumps move around, break up, join other clumps, and so on. Its interesting emergent behavior. Try changing the minDist and springValue values to see what happens.

image from book
Figure 12-6: Nodes in action

Nodes with connections

While it is pretty obvious that something is going on between the nodes here, I wanted to really point out the specific interaction between each pair of nodes. What better way than to draw a line between any two nodes that are interacting? Thats simple enough to do. I just altered the spring function a little bit:

 function spring(partA:MovieClip, partB:MovieClip):Void {       var dx:Number = partB._x - partA._x;       var dy:Number = partB._y - partA._y;       var dist:Number = Math.sqrt(dx*dx + dy*dy);       if(dist < minDist)       {  lineStyle(1, 0xffffff, 50);   moveTo(partA._x, partA._y);   lineTo(partB._x, partB._y);  var ax:Number = dx * springAmount;             var ay:Number = dy * springAmount;             partA.vx += ax;             partA.vy += ay;             partB.vx -= ax;             partB.vy -= ay;       } } 

If two nodes are interacting, Flash sets a line style and draws a line between them. You should also add the following as the first line in the onEnterFrame function, so you are starting fresh each frame:

 clear(); 

So, the nodes are now connected, as shown in Figure 12-7. This is OK, but I dont like the way the lines kind of snap on and off as nodes came in and out of range of each other.

image from book
Figure 12-7: Connect the dots

I want a more gradient approach. I figure that if two nodes are just under minDist apart, the line should be almost completely transparent. As they got closer and closer, the line should become brighter and brighter. So, if I say dist / minDist , this gives me a fraction from 0 to 1. Multiply by 100, and I get 0 to 100 for alpha. But this is backwards , because if dist equals minDist , then alpha will be 100, and as dist approaches 0, alpha will approach 0. OK, so take that number and subtract it from 100, which effectively reverses the effect. Heres the final line-drawing code:

 lineStyle(1, 0xffffff,  100 - dist / minDist * 100  ); moveTo(partA._x, partA._y); lineTo(partB._x, partB._y); 

This, to me, is a very beautiful effect, as shown in Figure 12-8. The result is in ch12_06.fla .

image from book
Figure 12-8: Subtle change, but a world of difference

Nodes with mass

While writing the chapter, I intrigued myself with the idea of nodes having mass, something I never thought of before. So, I tried it out and came up with ch12_07.fla. In it, I assign each node a random scale and mass based on that scale.

 function init():Void {       for(var i:Number=0;i<numParticles;i++)       {             var particle:MovieClip = attachMovie("particle",                                                  "p" + i, i);             particle._x = Math.random() * Stage.width;             particle._y = Math.random() * Stage.height;             particle.vx = Math.random() * 6 - 3;             particle.vy = Math.random() * 6 - 3;  particle._xscale = particle._yscale = 50 +   Math.random() * 600;   particle.mass = particle._xscale / 100;  } } 

This is used only when Im adding in the velocities in the spring function. I divide the velocity by the mass of each particle. This gives the larger ones more inertia.

 function spring(partA:MovieClip, partB:MovieClip):Void {       var dx:Number = partB._x - partA._x;       var dy:Number = partB._y - partA._y;       var dist:Number = Math.sqrt(dx*dx + dy*dy);       if(dist < minDist)       {             lineStyle(1, 0xffffff, 100 - dist / minDist * 100);             moveTo(partA._x, partA._y);             lineTo(partB._x, partB._y);             var ax:Number = dx * springAmount;             var ay:Number = dy * springAmount;  partA.vx += ax / partA.mass;   partA.vy += ay / partA.mass;   partB.vx -= ax / partB.mass;   partB.vy -= ay / partB.mass;  } } 

Since I was cutting down the overall effect of the spring, I increased the springValue to .0025. I like the overall effect, which you can see in Figure 12-9.

image from book
Figure 12-9: One more for the road

So what can you use nodes for? Personally, I think they are pretty cool to look at, and I even made a nice screensaver with them once. But I can imagine all kinds of game scenarios you could build with them for starters. Throw an Asteroids-type spaceship in there, and try to make it avoid the nodes. I bet that would be a nice challenge!



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