Collision Detection

4 12 2008

Whether it’s a shooting game, a car racing, a pin ball, or a pac man game, collision detection is one of the most important aspects in building games. Without proper colision detection none of these games can exist in Flash. I want to share a very basic collision detection using a ball bounce example. Below, see how the ball bounces back when it hits any of the side walls or the moving wall in the center.

BallBounce.swf

BallBounce in Flash AS3 using hitTestObject()

BallBounce in Flash AS3 using hitTestObject()

Here, collision is detected using two AS3.0 techniques:

1. movieclip1.hitTestObject(movieClip2)
2. checking the overlapping of x and y coordinates of the two movieclips

I have also used a custom event (BounceEvent) that helps in announcing when the ball hits a wall and specifically which wall(or which side.)

There are 5 classes being used in this example:

1. Ball: A ball that will move and bounce around.
2. MovingWall: A movieclip in the center that is constantly moving to create obstruction for the ball.
3. Splat: A movieclip object to show the collision effect.
4. BounceEvent: A custom event to announce that a ball has hit the wall.
5. main: This is the document class. Initiates all the objects and controls the collision detection.

Ball.as

package
{
	import flash.display.MovieClip;
	public class Ball extends MovieClip
	{
		public function Ball(xPos:Number, yPos:Number)
		{

			var b:MovieClip = new MovieClip();
			b.graphics.beginFill(0xFF9933);
			b.graphics.drawCircle(0, 0, 10);
			x = xPos;
			y = yPos;
			addChild(b);
		}
	}
}

Splat.as

package
{
	import flash.display.MovieClip;
	import fl.transitions.Tween;
	import fl.transitions.easing.*;
	public class Splat extends MovieClip
	{
		public function Splat()
		{
			alpha = 0;
		}

		public function explode(xPos:Number, yPos:Number):void
		{
			x = xPos;
			y = yPos;

			new Tween(this, "alpha", Strong.easeOut, 30, 0, 0.2, true);
		}
	}
}

MovingWall.as

package
{
	import flash.display.MovieClip;
	import flash.events.Event;
	public class MovingWall extends MovieClip
	{
		private var wallVelocityY:Number = 3;
		public function MovingWall(xPos:Number, yPos:Number)
		{
			x = 130;
			y = 40;
			setMotion();
		}
		private function setMotion():void
		{
			addEventListener(Event.ENTER_FRAME, moveWall);
		}
		private function moveWall(event:Event):void
		{
			y += wallVelocityY;
			if (y <= 40)
			{
				wallVelocityY = Math.abs(wallVelocityY);
			}
			else if (y >= 120)
			{
				wallVelocityY = -Math.abs(wallVelocityY);
			}
		}
	}
}

BounceEvent.as

package
{
	import flash.events.Event;
	public class BounceEvent extends Event
	{
		public static const BOUNCE:String = "Bounce";
		private var _side:String = "none";

		public function get side():String
		{
			return _side;
		}

		public function BounceEvent(type:String, side:String)
		{
			super(type, true);
			_side = side;
		}

		public override function clone():Event
		{
			return new BounceEvent(type, _side);
		}
	}
}

main.as

This is where the real action happens. First we instantiate the ball, movingWall, and the splat objects. Then we set the ball in motion. And then, using hitTestObject() we check when the ball hits the side walls. Using the custom BounceEvent we make an announcement when the ball hits a wall. The event also lets us know which wall has been hit. For the moving wall after checking with hitTestObject() we also need to find out which side of the wall has been hit. For that we check the overlapping of x and y coordinates of the ball and the moving wall.

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.display.MovieClip;

	public class main extends Sprite
	{
		private var ballVelocityX:Number = 2;
		private var ballVelocityY:Number = 3;
		private var ball:MovieClip;
		private var movingWall:MovingWall;
		private var splat:Splat;
		public function main()
		{
			stage.frameRate = 36;
			setGraphicObjects();
			startBallMotion();
		}
		private function setGraphicObjects():void
		{
			ball = new Ball(100, 100);
			addChild(ball);
			movingWall = new MovingWall(130, 40);
			addChild(movingWall);
			splat = new Splat();
			addChild(splat);
		}
		private function startBallMotion():void
		{
			ball.addEventListener(Event.ENTER_FRAME, moveball)
			addEventListener(BounceEvent.BOUNCE, bounceHandler);
		}
		private function moveball(event:Event):void
		{
			event.target.x += ballVelocityX;
			event.target.y += ballVelocityY;
			sideWallCollision();
			movingWallCollision();
		}
		private function sideWallCollision():void
		{
			if (ball.hitTestObject(wallLeft))
			{
				ballVelocityX = Math.abs(ballVelocityX);
				ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "left"));
			}
			else if (ball.hitTestObject(wallRight))
			{
				ballVelocityX = -Math.abs(ballVelocityX);
				ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "right"));
			}
			if (ball.hitTestObject(wallTop))
			{
				ballVelocityY = Math.abs(ballVelocityY);
				ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "top"));
			}
			else if (ball.hitTestObject(wallBottom))
			{
				ballVelocityY = -Math.abs(ballVelocityY);
				ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "bottom"));
			}
		}
		private function movingWallCollision():void
		{
			if (ball.hitTestObject(movingWall))
			{
				var movingWallLeft:Number = movingWall.x;
				var movingWallRight:Number = movingWall.x + movingWall.width;
				var movingWallTop:Number = movingWall.y;
				var movingWallBottom:Number = movingWall.y + movingWall.height;
				if (ball.x >= movingWallLeft)
				{
					ballVelocityX = -Math.abs(ballVelocityX);
					ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "center left"));
				}
				else if (ball.x <= movingWallRight)
				{
					ballVelocityX = Math.abs(ballVelocityX);
					ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "center right"));
				}
				if (ball.y >= movingWallTop)
				{
					ballVelocityX = -Math.abs(ballVelocityY);
					ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "center top"));
				}
				else if (ball.y <= movingWallBottom)
				{
					ballVelocityX = Math.abs(ballVelocityY);
					ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "center bottom"));
				}
			}
		}
		private function bounceHandler(event:BounceEvent):void
		{
			trace("Bounce on " + event.side + " side");
			splat.explode(event.target.x, event.target.y);
		}
	}
}

You can download all the files here:

BallBounce.zip

Advertisements

Actions

Information

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s




%d bloggers like this: