1. How to simulate the gravity a large body(such as a planet) has on a small body(such as a rock)
2. How to accurately detect collisions between circles(and no, we do not use hitTest)
This tutorial was written using Flash MX 2004(Flash 7) so if you've got that. You can grab the file Here and follow along.
The tutorial will look like this when complete, move the small circle with the arrow keys and when it gets close enough to the big circle, the big circle will start to pull it in.
So first we want to open up a new flash document and set the background to black. The width should be 550px and the height should be 400px.
Now Draw two circles on the document, one larger one to act as our planet, and a small one to act as our rock. You should have something like this:
Now select the smaller one go to Modify-->Convert to symbol and convert it to a movie clip. Name it "dot".
Now select your new movie clip and open the properties box. Under the pull-down menu where it identifies it as a symbol of type movie clip, there is a text box that allows you to name the instance. Name this instance "dot".
After doing this, you want to select your movie clip again and right click while its selected and choose "edit". We want to set the center of our circle at the center of the circle. Make sure the crosshair is at the center of your circle in the edit clip screen.
Now back out to the main screen and select the smaller circle again. Open up the actions box:
And type this code in:
Code:
onClipEvent(load)
{
this.radii=this._width/2;
this.xspeed=0;
this.yspeed=0;
}
onClipEvent(enterFrame)
{
if(Key.isDown(Key.RIGHT))
{
this.xspeed=5;
}
else if(Key.isDown(Key.LEFT))
{
this.xspeed=-5;
}
if(Key.isDown(Key.DOWN))
{
this.yspeed=5;
}
else if(Key.isDown(Key.UP))
{
this.yspeed=-5;
}
this._x+=this.xspeed;
this._y+=this.yspeed;
}
The onClipEvent(load) are the actions that happen when the movie clip first loads. The actions in onClipEvent(enterFrame) are the actions that happen on each successive frame entry(usually movies run at 20-25fps). So upon loading, we want to define the radius of the clip. Since this is a circle, it is the width divided by two. We also set the initial x and y speeds to zero so our circle starts in a stationary position.
Now in onClpEvent(enterFrame) we simply have some code that detects whether any of the arrow keys are pressed and if they are we set the x and y movement directions accordingly. At the end we move the circle's x and y position by whatever the circle's current x and y speed(s) are at.
We are done with the small circle(your rock), now we want to move on to the planet(the bigger circle). So, select it and also convert it to a symbol and call the symbol "planet". Go into edit mode for this movie clip also and center the crosshair in the middle of the plnaet. We will put the code for the gravity in the planet movie clip. Now, in real-life the physics formula for acceleration due to gravity is:
F = (m1*m2)/(d*d)
Where Mass 1 and Mass 2 are the masses of the two objects and d is the distance between the objects. For simplicity, the mass of our rock will be one for this tutorial. If you need it to be more than one, you can change it to something else.
Open up the actions box for the planet movie clip and type this in:
So in the load action, we want to specify the mass of the planet(in this case 10,000). We also want to specify gdistance, the distance where the gravity of the planet will start to have effect on the rock. I've set it at 250. We also set the radius of the planet to its width divided by 2. We set all the distances to zero because we are going to calculate them within enterFrame, or on each successive frame entry.
Now in the enterFrame event we first set maxalloweddistance, the distance allowed before the rock collides into the planet and dies, to be the sum of their two radii. xdist and ydist are simply the x and y distances of the rock from the planet. The totaldistance is the square-root of the sum of the squares of the xdist and ydist. To avoid the divide by zero problem, we say if the totaldistance is 0 between the two objects, then set it to 1.
Next we state that if the totaldistance between the two objects is less than the range where gravity has effect, then gravity will start to pull.
If the rock is within the gravitational pull range of the planet then we have code such as:
What this does is that if the x position of the planet is greater than the x position of the rock, then the rock's xspeed will increase by the fraction of the xdist over the totaldist times the force of the gravitational pull. I have four cases like this for the x and y forces of the gravitational pull. This simulates gravity according to the gravitational force formula. The last thing is that we check is if the total distance between the two planets is less than the sum of their two radii. If it is, then we remove the small rock movie clip because it has collided with the planet. We swap the depth first because sometimes if this is not done, the clip will not remove itself.
Note that without the remove code, the small circle will not stay in the center of the large circle. Instead if will get pulled and then whipped out off the screen. This does simulate real life. If a black hole were to pass near the solar system, earth would most likely not get sucked in but get flung out to the
icy cold corners of the universe and we'd all freeze to death there. Nice thought, isn't it?