2.5 Collision Detection

This exercise aims to showcase how to use collision detection in AS3. We will use an example with a moving object (a circle) and a static, but dragable object (a rectangle). By dragging the rectangle to intersect the circle, we will be able to change its trajectory.

1. First, some thoughts on collision detection. Quoting Wikipedia:

In physical simulations, video games and computational geometry, collision detection involves algorithms for checking for collision, i.e. intersection, of two given solids. Simulating what happens once a collision is detected is sometimes referred to as “collision response” (see collision response, physics engine and ragdoll physics). Collision detection algorithms are a basic component of 3D and 2D video games. Without them, characters could go through walls and other obstacles.

(from: http://en.wikipedia.org/wiki/Collision_detection)

As you can see, this is very useful in interactive projects. Possibly the easiest way to implement this in Flash is by using the hitTest() method inside a conditional, to check if one object has hit another.

2. Let’s now set up our exercise. We will begin by drawing our circle (let’s call it “ball”) and our rounded corners rectangle (simply “rectangle”). The ball will be non-interactive, therefore a simple shape. The rectangle will be dragable, so we should create it as a sprite:

var ball:Shape = new Shape();
stage.addChild(ball);
ball.x=275;
ball.y=200;
ball.graphics.beginFill(0xFF00FF);
ball.graphics.drawCircle(0, 0, 50);

var rectangle:Sprite = new Sprite();
stage.addChild(rectangle);
rectangle.x=100;
rectangle.y=200;
rectangle.graphics.beginFill(0x00008B);
rectangle.graphics.drawRoundRect(0, 0, 100, 30, 10);
rectangle.buttonMode=true;

The last line, as you remember, allows the hand cursor to show up.

3. Now, let’s create some code to make the rectangle dragable, entirely similar to what we did in the previous exercise:

rectangle.addEventListener(MouseEvent.MOUSE_DOWN, dragRectangle);
function dragRectangle(e:MouseEvent):void {
rectangle.startDrag();
}
rectangle.addEventListener(MouseEvent.MOUSE_UP, releaseRectangle);
function releaseRectangle(e:MouseEvent):void {
stopDrag();
}

4. We will now create a continuous function to make the ball move. Let’s create a numerical variable out of the function which will define the “speed” with which the ball will move at the current frame rate (that is, the number of pixels added or subtracted to the ball’s y property each time the function runs). We will add the event Event.ENTER_FRAME to the stage, which will trigger a function that we will entitle “moveBall”. Inside “moveBall”, we add the “speed” to ball.y, with the “+=” operator:

var speed:Number=10;
stage.addEventListener(Event.ENTER_FRAME, moveBall);
function moveBall(e:Event):void {
ball.y+=speed;
}

5. However, if nothing is done to stop it, the ball will disappear towards the bottom of the screen. Similarly to a previous exercise, let’s use a conditional to prevent that. However, this time we would like that the ball keeps bouncing up and down every time it hits the bottom or the top of the screen.

The bottom of the stage is by default pixel 400, but let’s use stage.stageHeight instead, since it accurately determines the height of the stage (useful in case it will be resized). The top of the stage is pixel 0. So, if ball.y is lesser than one (ball disappearing on top), or if ball.y is greater that stage.stageHeight (ball disappearing on bottom), we could simply invert the sign of speed, effectively inverting the direction of movement. To change the sign of the speed variable, we can simply multiply it by -1 using the “*=” operator.

Our redesigned function would look like this:

function moveBall(e:Event):void {
ball.y+=speed;
if (ball.y < 0) {
speed*=-1;
}
if (ball.y > stage.stageHeight) {
speed*=-1;
}
}

6. We still need to add one thing to the function – collision detection. For that, we need one more conditional, to test if the ball has hit the rectangle. If so, it should also change direction. This conditional would be coded as follows:

if (ball.hitTestObject(rectangle)) {
speed*=-1;
}

And the whole function would now look like this:

function moveBall(e:Event):void {
ball.y+=speed;
if (ball.y < 0) {
speed*=-1;
}
if (ball.y > stage.stageHeight) {
speed*=-1;
}
if (ball.hitTestObject(rectangle)) {
speed*=-1;
}
}

7. To conclude, let’s bump up the frame rate to 60 fps, to make the animation smoother:

stage.frameRate=60;

8. You can now play with the rectangle, and drag it around so that it intersects with the ball.

9. The whole code would look like this:

var ball:Shape = new Shape();
stage.addChild(ball);
ball.x=275;
ball.y=200;
ball.graphics.beginFill(0xFF00FF);
ball.graphics.drawCircle(0, 0, 50);
var rectangle:Sprite = new Sprite();
stage.addChild(rectangle);
rectangle.x=100;
rectangle.y=200;
rectangle.graphics.beginFill(0x00008B);
rectangle.graphics.drawRoundRect(0, 0, 100, 30, 10);
rectangle.buttonMode=true;

rectangle.addEventListener(MouseEvent.MOUSE_DOWN, dragRectangle);
function dragRectangle(e:MouseEvent):void {
rectangle.startDrag();
}
rectangle.addEventListener(MouseEvent.MOUSE_UP, releaseRectangle);
function releaseRectangle(e:MouseEvent):void {
stopDrag();
}

var speed:Number=10;
stage.addEventListener(Event.ENTER_FRAME, moveBall);
function moveBall(e:Event):void {
ball.y+=speed;
if (ball.y < 0) {
speed*=-1;
}
if (ball.y > stage.stageHeight) {
speed*=-1;
}
if (ball.hitTestObject(rectangle)) {
speed*=-1;
}
}
stage.frameRate=60;

And the final result would look like this:

Download files: ex11-hittest.zip

Advertisements

About Nuno Correia

audiovisuals+interaction
This entry was posted in 2. Controlling Audiovisual Objects and tagged . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s