Random Distribution

From time to time, you may want to create a bunch of objects and place them at random positions . Youve seen how this is done many times throughout the book. Here well look at a few different methods of doing this, and the different results that they will give you.

Square distribution

If you want the objects to randomly cover the entire stage, thats pretty simple. Just choose a random number up to the stages width for x, and a random number up to its height for y. In fact, you did just that in the preceding section:

 for(var i:Number = 0;i<numDots;i++) {       var dot:MovieClip = attachMovie("dot", "dot" + i, i);       dot._x = Math.random() * Stage.width;       dot._y = Math.random() * Stage.height;       ... 

But say you wanted to kind of clump the dots in near the center of the stage, say 100 pixels to either side, top or bottom of the center. You could do something like the following, which is in ch19_03.fla :

 var numDots:Number = 50; init(); function init():Void {       for(var i:Number = 0;i<numDots;i++)       {             var dot:MovieClip = attachMovie("dot", "dot" + i, i);  dot._x = Math.random() * 200 - 100 + Stage.width / 2;   dot._y = Math.random() * 200 - 100 + Stage.height / 2;  } } 

This creates a random number from ˆ 100 to +100 and adds it to the center point of the stage, so all of the dots will be no farther than 100 pixels on either axis from the center. Figure 19-3 shows what that gives you.

image from book
Figure 19-3: Randomly placed dots

Not too bad. But if you crowd them in a bit more by making a lot more dots (300) and reducing the area to 100 by 100, youll notice something odd starting to happen. Heres the code from ch19_04.fla :

 var numDots:Number = 300; init(); function init():Void {       for(var i:Number = 0;i<numDots;i++)       {             var dot:MovieClip = attachMovie("dot", "dot" + i, i);             dot._x = Math.random() * 100 - 50 + Stage.width / 2;             dot._y = Math.random() * 100 - 50 + Stage.height / 2;       } } 

And Figure 19-4 shows what you get.

image from book
Figure 19-4: This method starts to form a square. Not so random looking anymore.

As you see, the dots are starting to form a square. Maybe thats OK, but if you are trying to make some kind of explosion or star system or something of the sort , a square doesnt look too natural. If a square distribution is not exactly what you are looking for, try moving on to the next technique.

Circular distribution

While slightly more complex than a square distribution, circular distribution really isnt too hard to do. First you need to know the radius of your circle. Lets keep it at 50, to match the last example. This will be the maximum radius that a dot can be placed from the center. Youll take a random number from zero to that number to use as the radius for each dot. Then youll choose a random angle from 0 to PI * 2 radians (360 degrees), and use a quick bit of trig to find the x and y position of the dot. Heres the code from ch19_05.fla :

 var numDots:Number = 300; var maxRadius:Number = 50; init(); function init():Void {       for(var i:Number = 0;i<numDots;i++)       {             var dot:MovieClip = attachMovie("dot", "dot" + i, i);  var radius:Number = Math.random() * maxRadius;   var angle:Number = Math.random() * (Math.PI * 2);   dot._x = Math.cos(angle) * radius + Stage.width / 2;   dot._y = Math.sin(angle) * radius + Stage.height / 2;  } } 

And that gives you a picture like the one in Figure 19-5.

image from book
Figure 19-5: Circular random distribution

This is much more natural for most of the types of applications I mentioned earlier. However, you might notice that the dots seem to be even more clumped around the center of the circle. This is because an even distribution exists along the radius, meaning there are as many dots in the center as near the edge. But because the center has less space, they are more crowded.

Again, this may be fine for some applications, but Sean OShell (http://www.pixelwit.com) once challenged me to come up with a way of making the dots appear more uniformly distributed throughout the circle. I have to admit I was stumped, and the solutions I tried were pretty complex. Finally, he gave me a very simple solution, as you can see in ch19_06.fla :

 var numDots:Number = 300; var maxRadius:Number = 50; init(); function init():Void {       for(var i:Number = 0;i<numDots;i++)       {             var dot:MovieClip = attachMovie("dot", "dot" + i, i);             var radius:Number =  Math.sqrt(Math.random())  * maxRadius;             var angle:Number = Math.random() * (Math.PI * 2);             dot._x = Math.cos(angle) * radius + Stage.width / 2;             dot._y = Math.sin(angle) * radius + Stage.height / 2;       } } 

By taking the square root of the random number, it has a bias towards 1 and away from 0, which is just enough to smooth out the distribution. You can see the result in Figure 19-6. Nice one, Sean!

image from book
Figure 19-6: A smoother distribution

Biased distribution

Finally, you may want to give the random objects free range over the entire stage, but have them tend to show up in the middle area. Youd find some out on the edges, but the closer to the center you got, the more there would be. This would be somewhat like the first circular example, but applied to a rectangular area.

You do this by generating multiple random numbers for each position, and then averaging them to get the final value. For example, say the stage is 500 pixels wide. If you generate an x position for each object with just one random number, then each object has an equal chance of being anywhere in that range. But if you generate two random numbers from 0 to 500, and take the average, theres a bit higher chance that it will be somewhere in the middle rather than out towards the edges.

Lets look at that in a little more depth. There is some chance that both numbers might be in a high range, say from 300 to 500. Theres about the same chance that both might be in a low range, from 0 to 200. But theres a higher chance that one will be high and one low, or one middle and one high or low, or even both in the middle. All of these possibilities will average out to place the dot closer to the middle.

OK, lets see it in code. As usual, youll start on one dimension. Using the same dot movie clip as the previous examples, heres the code ( ch19_07.fla ):

 var numDots:Number = 300; var maxRadius:Number = 50; init(); function init():Void {       for(var i:Number = 0;i<numDots;i++)       {             var dot:MovieClip = attachMovie("dot", "dot" + i, i);             var x1:Number = Math.random() * Stage.width;             var x2:Number = Math.random() * Stage.width;             dot._x = (x1 + x2) / 2;             dot._y = Stage.height / 2 + Math.random() * 50 - 25;       } } 

Here you are generating two random numbers, x1 and x2, and setting the dots x position to the average of them. The y position is simply randomly near the center. This gives you something like this:

image from book
Figure 19-7: Biased distribution with one iteration

The effect isnt too pronounced here, but you can see that there is a bit more clumping in the center, and more space at the edges. Creating more random numbers and averaging them will make it more obvious. Youll move this into a for loop to make it dynamic ( ch19_08.fla ):

 var numDots:Number = 300; var maxRadius:Number = 50;  var iterations:Number = 6;  init(); function init():Void {       for(var i:Number = 0;i<numDots;i++)       {             var dot:MovieClip = attachMovie("dot", "dot" + i, i);  var x:Number = 0;   for(var j:Number = 0;j<iterations;j++)   {   x += Math.random() * Stage.width;   }   dot._x = x / iterations;  dot._y = Stage.height / 2 + Math.random() * 50 - 25;       } } 

Here the iterations variable controls how many numbers you will average. You start out with the variable x equal to zero, and add each random number to it. Finally, you divide that by the number of iterations for the final value. This gives you a picture like the one in Figure 19-8.

image from book
Figure 19-8: Biased distribution with six iterations

It is now easy to do the same thing for the y axis, and in ch19_09.fla , you do just that:

 var numDots:Number = 300; var maxRadius:Number = 50; var iterations:Number = 6; init(); function init():Void {       for(var i:Number = 0;i<numDots;i++)       {             var dot:MovieClip = attachMovie("dot", "dot" + i, i);             var x:Number = 0;             for(var j:Number = 0;j<iterations;j++)             {                   x += Math.random() * Stage.width;             }             dot._x = x / iterations;  var y:Number = 0;   for(var j:Number = 0;j<iterations;j++)   {   y += Math.random() * Stage.height;   }   dot._y = y / iterations;  } } 

This gives you a distribution like the one in Figure 19-9.

image from book
Figure 19-9: Two-dimensional biased distribution.

To me, this is the most random, explosive, star-system-like distribution of them all, though it is also the most intensive to generate. At any rate, you now have at least four ways to generate random positions.



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