Gravity

The first kind of particle attraction Im going to talk about is gravity. Now, I can hear you saying, Didnt you cover that way back in Part Two of the book? True, I did, but that was gravity as seen from very close up.

Standing on earth, gravity has a pretty simple description: It pulls things down. In fact, it pulls things down at a very specific rate. The acceleration it applies is equal to about 32 feet per second per second. One way of expressing acceleration is by how much velocity it adds over a specific time period. Gravity makes things go 32 feet per second faster, every second it pulls on them. You can go to the tallest mountain or the lowest valley, and that number 32 isnt going to change enough for you to notice (that is, without some sensitive instruments).

Gravitational force

When you start stepping back, you see that actually, the farther away you are from a planet or large body, the less the gravity becomes. This is a very good thing. Otherwise, we would all be sucked into the sun, which would be sucked into every other sun and planet, which would all wind up smashed together pretty quickly. So, when you get out to the point where you can refer to planets as particles, the distance between them very much affects the gravitational pull.

How much the distance affects the force is very easy to describe. Its inversely proportional to the square of the distance. Well, maybe that needs some explanation. First, gravity is also very tied in with mass. The more mass something has, the more force it will pull on other things, and the more it will be pulled by them. There is also something called the gravitational constant (abbreviated G ) that fits in there. Heres the full equation for the force of gravity:

 force = G * m1 * m2 / distance  2  

In plain English, the force of gravity on an object by another object is equal to this gravitational constant, times both masses, divided by the square of the distance between them. Hmmm. . . that looks pretty simple. You just need to know what this gravitational constant is, and youll be all set. Well, heres the official definition of it:

 G = (6.6742  0.0010) * 10  -11  * m  3  * kg  -1  * s  -2  

Now, if you want to figure out coding that in ActionScript, go for it. For me, when I see something like that, I immediately know Im going to be doing some faking soon. You want to know how I usually fake it? I write my gravity formula like this:

 force = m1 * m2 / distance  2  

Yup, thats right, I ignore G . And now Ill plug in my usual disclaimer. If you are doing a Flash-based space shuttle guidance system for NASA, you should probably leave G in there. But if youre coding up the next great online space wars game, youre probably going to be able to live without it.

Now that you have a formula, lets put it into code. Set up the onEnterFrame function first, and have it call a gravitate function so you can separate the code that handles gravity:

 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;       }       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];                   gravitate(partA, partB);             }       } } 

Here, youre just moving all the particles with basic motion code in a single for loop, and then doing a double for loop to get their interactions. Once you have partA and partB , you pass these two particles to the gravitate function. Heres that function:

 function gravitate(partA:MovieClip, partB:MovieClip):Void {       var dx:Number = partB._x - partA._x;       var dy:Number = partB._y - partA._y;       var distSQ:Number = dx*dx + dy*dy;       var dist:Number = Math.sqrt(distSQ);       var force:Number = partA.mass * partB.mass / distSQ;       var ax:Number = force * dx / dist;       var ay:Number = force * dy / dist;       partA.vx += ax / partA.mass;       partA.vy += ay / partA.mass;       partB.vx -= ax / partB.mass;       partB.vy -= ay / partB.mass; } 

First, you find the dx and dy between the two particles, and the total distance. Remember that the formula for gravityforce = G — m1 — m2 / distance2contains the distance squared. Normally, I would calculate distance all at once using dist = Math.sqrt(dx*dx + dy*dy) . But then to get distance squared, I would be squaring something that was a square root! Thats double work. If I just use the variable distSQ to grab a reference to dx*dx + dy*dy before I take the square root, I save myself that calculation.

Then I find the total force by multiplying the masses and dividing by the distance squared. Then I figure out the total acceleration on the x and y axes. Again, Im using the shortcut I discussed at the very end of Chapter 9, using dx / dist instead of Math.cos(angle) and dy / dist instead of Math.sin(angle) . This saves me from needing to use Math.atan2(dy, dx) to find the angle in the first place.

Now, notice that I keep talking about the total force and the total acceleration. This is the combined force acting between the two objects. You need to divvy it up between the two, based on their masses. If you think of the earth and the sun, there is a particular force between them. It is the product of their masses, divided by the square of their distance. So, they are pulling towards each other with that total force. The earth is being pulled towards the sun, and the sun is being pulled towards the earth. Obviously, the earth gets a lot more of that acceleration because it has much less mass than the sun. So, to get the individual acceleration for either object in the system, you divide the total acceleration by that objects mass. Thus, you have the last four lines of the formula. Notice that partA gets the acceleration added, and partB gets it subtracted. This is merely due to the order of subtraction I used to get dx and dy .

The final code for this example can be found in ch12_01.fla . Go ahead and test it. You should see that the particles start out motionless, but are slowly attracted to each other, something like Figure 12-1. Occasionally, a couple of them will start sort of orbiting around each other. But mostly what happens is that they hit and fly off in opposite directions.

image from book
Figure 12-1: We have particles!

Is this speeding off a bug? Well, yes and no. Its not a bug in the code. Its actually expected behavior, and is something called the slingshot effect . Its what NASA uses to send probes into deep space. As an object gets closer and closer to a planet, it feels more and more acceleration, and it starts traveling with a very high velocity. If you aim it just right, so it comes very close to the planet, but just misses it, that object will whip off into space too fast for the planets gravity to capture it. All that speed with zero fuelnow thats efficiency.

But back to Flash. What is happening here is that the objects are getting to within a very small distance of each otheralmost zero distance. Thus, the force between them becomes huge, almost infinite. So, mathematically, its correct, but from a simulation viewpoint, its unrealistic . What should happen is that if the objects get close enough together, they collide. If you aimed that space probe directly at the planet, it would not zoom past it at infinite speed. It would make a crater.

Collision detection and reaction

So, for your particles, you need to have some kind of collision detection and reaction. What you do is up to you. You could have them explode and disappear. You could have one particle disappear and add its mass to the other one, as if they had joined.

For this example, I realized that I had some very nice collision and reaction code left over from the previous chapter, in a function called checkCollision . Lets just plug that right in here, like so ( ch12_02.fla ):

 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;       }       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];  checkCollision(partA, partB);  gravitate(partA, partB);             }       } } 

Only that one line in bold has changed. Plus, of course, I copied and pasted the checkCollision and rotate functions into the file.

Now the particles are attracted to each other, but bounce off when they hit. Try changing the mass of the particles and see how they attract differently. You can even do bizarre things like giving the particles negative mass and watching them repel each other!

In the file ch12_03.fla , I kept everything the same, but added a couple of lines to the init function:

 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 = 0;             particle.vy = 0;  particle._xscale = particle._yscale = 100 +   Math.random() * 500;   particle.mass = particle._xscale / 100;  } } 

This just gives each particle a random size and a mass based on that size , as you can see in Figure 12-2. Things start to get interesting.

image from book
Figure 12-2: Colliding planets?

Orbiting

Finally, just to show you how realistic this gets, lets set up a simple planetary system, with a sun and planet. Make a large sun with a mass of 10,000, and a planet with a mass of 1. Then move the planet a distance away from the sun and give it some velocity perpendicular to the line between it and the sun. The setup looks something like Figure 12-3.

image from book
Figure 12-3: Setting up the stage

If you get the masses, distance, and velocity just right, you should be able to get the planet into orbit . It took some trial and error, but I came up with whats in ch12_04.fla . All Im going to show you here is the init code. The only other change to the file was to set the numParticles variable to 2.

 function init():Void {       var sun:MovieClip = attachMovie("particle", "p" + 0, 0);       sun._x = Stage.width / 2;       sun._y = Stage.height / 2;       sun._xscale = sun._yscale = 400;       sun.vx = 0;       sun.vy = 0;       sun.mass = 10000;       var planet:MovieClip = attachMovie("particle", "p" + 1, 1);       planet._x = Stage.width / 2+ 200;       planet._y = Stage.height / 2;       planet.vx = 0;       planet.vy = 7;       planet.mass = 1; } 

As a little extra, check out ch12_04a,fla , which draws a line tracing the orbit. You can wind up with some interesting patterns.



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