Making sure that shapes don’t hit in Android AIR

Basic Tutorials concerning: GUI, Views, Activites, XML, Layouts, Intents, ...

Making sure that shapes don’t hit in Android AIR

Postby WahunaApps » Tue May 24, 2011 8:14 pm

Making sure that shapes don’t hit in Android AIR
Table of contents
  • 1. Tutorial
  • 1.1 Creating a circle
  • 1.2 Creating multiple random circles
  • 1.3 Interactivity with the circle?
  • 1.4 Testing boundaries
  • 1.5 Example


This tutorial was made for all the developers who want to generate random shapes on the screen but do not want them to overlap (hit) each other.

You could use the method hitTestObject() but that didn't work very well for me, so I decided to use my own method.


1.1 Creating a circle
We want to create a shape (for example: a circle) and add it to the stage.

First, we'll make a new instance from the class MovieClip and name it ‘circle’.
Code: Select all
var circle:MovieClip = new MovieClip();

Note that we still need to import the library ‘MovieClip’.
Code: Select all
import flash.display.MovieClip;

Then we start filling the circle with any given color. Note that the color you want to use needs to be in hexadecimal format, ranging from 0x000000 (BLACK) to 0xFFFFFF (white).
Code: Select all
circle.graphics.beginFill(0x000000, 1);

Next we can start drawing our circle. One important matter is the circle’s radius.
Note that the width of the circle is twice the radius.
Code: Select all
circle.graphics.drawCircle(0, 0, “radius”);

Next we set a new x and y coordinate for our circle. We will be replacing “a number” by a random value.
Code: Select all
circle.x = “a number”;
   circle.y = “a number”;

After we’ve set the properties for our circle, we can add this on the stage.
Code: Select all
addChild(circle);


Full code:
Code: Select all
import flash.display.MovieClip;

var circle:MovieClip = new MovieClip();

circle.graphics.beginFill(0x000000, 1);
circle.graphics.drawCircle(0, 0, 20);

circle.x = 40;
circle.y = 40;

addChild(circle);

In this code, the radius of the circle is 20, the width of the circle is 40 (2x the radius), the color of the circle is black (0x000000) and the circle is centered at (40, 40) =(x, y) on the stage.
If you run the application, you should see a window with a black circle in the top, left corner.


1.2 Creating multiple random circles
Now you can simply repeat the previous process of creating a circle by putting the code into a FOR statement.
Code: Select all
import flash.display.MovieClip;

for(var i:Number = 0; i < 5; i++)
{
   var circle:MovieClip = new MovieClip();

   circle.graphics.beginFill(0x000000, 1);

   circle.graphics.drawCircle(0, 0, 20);

   circle.x = Math.floor(Math.random() * ((stage.stageWidth - 20) - (0 + 20)) + (0 + 20));
   circle.y = Math.floor(Math.random() * ((stage.stageHeight - 20) - (0 + 20)) + (0 + 20));

   addChild(circle);
}


The only thing that has changed is the FOR statement which has been added so that the process of creating a circle will be repeated for a given number of times.

Now you might have noticed that it is useless of creating a circle on the same place for several times (else you wouldn’t be reading this tutorial). That’s when we call in the Random class, which will randomly generate an X and Y coordinate.

You can also use the random class for other purposes such as a random color or a random size. It’s up to you.
Note that the code for creating a random number is a little longer than is needed to. It is because I’ve put in a little extra control on the x and y coordinate of the circle.

If you would be using this code;
Code: Select all
circle.x = Math.round(Math.random()*stage.stageWidth);
   circle.y = Math.round(Math.random()*stage.stageHeight);


you will also generate a random x and y coordinate between 0 and the width/height of your stage, but if you run the application a couple of times, you will see that some of the circles will be generated outside of the window.

Of course, we don’t want that to happen, so that’s why we put in a little extra control so the circle will be generated between the boundaries of the stage.

Now you might be wondering, if the x coordinate is 0, why does the circle still go outside the stage? Well it’s because the circle will center around it’s x and y coordinates. That means that if you use 0 for your x and y coordinates, the top left corner of the stage will be the exact center of the circle.

A simple figure which shows the (x, y) value of a shape:
Image

That’s why we use the following code for generating a random x and y coordinate:
Code: Select all
circle.x = Math.floor(Math.random() * ((stage.stageWidth - 20) - (0 + 20) ) + (0 + 20));
   circle.y = Math.floor(Math.random() * ((stage.stageHeight - 20) - (0 + 20) ) + (0 + 20));



2.3 Interactivity with the circle?
If you want to use some interactivity with each circle, such as adding a Mouse Listener, you’ll have to put each circle into an array.

Define a new array using the following code:
Code: Select all
var arrCircles:Array = new Array();

After the “addChild(circle)” line, you can add the circle to the array:
Code: Select all
arrCircles[i] = circle;


Full code:
Code: Select all
import flash.display.MovieClip;

var arrCircles:Array = new Array();

for(var i:Number = 0; i < 5; i++)
{
   var circle:MovieClip = new MovieClip();

   circle.graphics.beginFill(0x000000, 1);

   circle.graphics.drawCircle(0, 0, 20);

   circle.x = Math.floor(Math.random() * ((stage.stageWidth - 20) - (0 + 20)) + (0 + 20));
   circle.y = Math.floor(Math.random() * ((stage.stageHeight - 20) - (0 + 20)) + (0 + 20));

   addChild(circle);

   circle.addEventListener(MouseEvent.CLICK, clicked);

   arrCircles[i]= circle;
}
function clicked(event:MouseEvent):void
{
   var bron:Object = event.target;

   for(var i:Number = 0; i < arrCircles.length; i++)
   {
      if(bron == arrCircles[i])
      {
         trace(“You have clicked on circle nr: “ + (i+1));
      }
   }
}


This method allows you to add event listeners to each circle. After an event has been activated, use the FOR and IF statements to know what circle has called the event method.
Note that if you want to add event listeners to the circles, you have to add the listener to each of the circles you generate in the FOR statement.


1.4 Testing boundaries
Still, when you’re using the Random class to generate random x and y coordinates, there’s a slight chance a circle will overlap another one. If you only generate up to 2 circles, this isn’t much of a big deal, but if you’re generating more circles, the chance of one overlapping another is getting bigger.

Note that this method is only to be used when creating more than 1 circle. Also, this method will only work if there’s still room enough to make a circle.

Let’s begin, shall we?
The method we will be using to check if a circle hits another one is going to be a typed method which returns a true/false value.

First of all, we’re going to put the code where we generate the x and y coordinates between a DO WHILE statement, cause we want to generate an x and y each time the old values are within the borders of another circle.

Full code:
Code: Select all
import flash.display.MovieClip;

var arrCircles:Array = new Array();

for(var i:Number = 0; i < 5; i++)
{
   var circle:MovieClip = new MovieClip();

   circle.graphics.beginFill(0x000000, 1);

   circle.graphics.drawCircle(0, 0, 20);

   do
   {
      circle.x = Math.floor(Math.random() * ((stage.stageWidth - 20) - (0 + 20)) + (0 + 20));
      circle.y = Math.floor(Math.random() * ((stage.stageHeight - 20) - (0 + 20)) + (0 + 20));
   } while(CheckHit(circle.x-radius, circle.x + radius, circle.y - radius, circle.y + radius, i));

   addChild(circle);

   circle.addEventListener(MouseEvent.CLICK, clicked);

   arrCircles[i]= circle;
}

function clicked(event:MouseEvent):void
{
   var bron:Object = event.target;

   for(var i:Number = 0; i < arrCircles.length; i++)
   {
      if(bron == arrCircles[i])
      {
         trace(“You have clicked on circle nr: “ + (i+1));
      }
   }
}
function CheckHit(leftBorderNew:Number, rightBorderNew:Number, topBorderNew:Number,            bottomBorderNew:Number, count:Number):Boolean
{   
var leftBorderOld:Number = 0;
var rightBorderOld:Number = 0;
var topBorderOld:Number = 0;
var bottomBorderOld:Number = 0;
   var hit:Boolean = false;
         
   if(count == 0)
{
      hit = false;
   }
   else
   {
      for(var i:Number = 0; i < count; i++)
      {
         var oldCircle:MovieClip = arrShapes[i];
            
         leftBorderOld = (oldCircle.x - (oldCircle.width/2));
         rightBorderOld = (oldCircle.x + (oldCircle.width/2));
         topBorderOld = (oldCircle.y - (oldCircle.width/2));
         bottomBorderOld = (oldCircle.y + (oldCircle.width/2));
               
         if((leftBorderOld <= rightBorderNew) && (rightBorderOld >=                     leftBorderNew))
            if((bottomBorderOld >= topBorderNew) &&
                (topBorderOld <= bottomBorderNew))
            {
               hit = true;
            }
         }
      }
   }
         
   return hit;
}


This method will return ‘true’ if the new generated circle comes hits an previous created circle and false if the circle doesn’t hit any of the older circles. In case of a ‘true’, a new x and y coordinate will be generated, else, the DO WHILE statement will be broken and the circle will be added to the stage.

1.5 Example
I would like to take our new application ‘Wordz’ as an example for the checkhit() method.

It is a simple android application where the objective is to click the letters of a given word in order as fast as you can.

The different letters of each word are generated with a circle on the stage, separated from each other so the user gets a good view.

Image
WahunaApps
Freshman
Freshman
 
Posts: 2
Joined: Thu May 05, 2011 11:36 am

Top

Return to Novice Tutorials

Who is online

Users browsing this forum: Yahoo [Bot] and 3 guests