Building the MYFJ game

Wooo, ok so as I’m writing this I feel like a load has been lifted from my shoulders. Over the past few weeks I have been building a new game to promote MYFJ that has been using newly learned skills with Papervision3D.

One of the biggest challenges has been the collision detection between a point and a plane. With alot of research, playing with code and a few lengthy talks with fellow developers, I now have a piece of code that is working nicely. Below are some of the solutions which I have descovered.

I also want to say thanks to Seb Lee-Delisle and Marc Binsted for their help and code examples. Seb has written a few interesting articles about Predictive collision detection techniques and Predicting circle line collisions that I highly recomend. At first Vector Math blew my mind, but with some time, I have been able to get my head around it and get a better understanding of it.

Now I dont like to make things easy for myself, not only am I using a 3D engine, but my planes are rotated on the Z axis (they were rotating on the Y axis as well, but that was just causing way to many problems). So because of the Z axis rotation I couldn’t just work out if the point falls within an area using half the planes height and width. But first it was a case of working out the distance between the point and the plane, and to get there I needed to get the dot product. The below example uses the Number3D class within Papervision3D.

// GET THE DISTANCE FROM A POINT TO THE PLANE'S WORLD POSITION AS A DOT PRODUCT
   public function distanceToWorldPoint( p:Number3D ):Number
   {
// 	TEMP BECOMES THE VECTOR BETWEEN THE POINT AND THE PLANES POSITION
//	copyFrom COPIES THE X,Y,Z PROPERTIES OF P
	this.temp.copyFrom( p );
 
//	MINUS THE POSITION FROM TEMP - THE SAME AS -= OPERATOR
	this.temp.minusEq( this.w_position );
 
//	RETURN THE DOT PRODUCT BETWEEN THE POINT AND THE PLANE
	return Number3D.dot( this.temp, this.normal );
   }

Once I had the dot product of the current distance I then had to work out the distance in the next frame, by adding the points velocity of the points co-ordinates. With these two values you can get the time that collision will occur, but I only needed to know when the point was close to the plane. When I knew this I could then check to see if my point was within the planes triangle using the function below.

// CHECK TO SEE IF A POINT IS WITHIN A TRIANGLE
   static public function pointInTriangle2( p:Number3D, a:Number3D, b:Number3D, c:Number3D ):Boolean
   {
//	COMPUTE VECTORS
	var v0:Number3D 	= Number3D.sub( c, a )
	var v1:Number3D		= Number3D.sub( b, a )
	var v2:Number3D 	= Number3D.sub( p, a )
 
//	COMPUTE DOT PRODUCTS
	var dot00:Number	= Number3D.dot( v0, v0 )
	var dot01:Number 	= Number3D.dot( v0, v1 )
	var dot02:Number 	= Number3D.dot( v0, v2 )
	var dot11:Number 	= Number3D.dot( v1, v1 )
	var dot12:Number 	= Number3D.dot( v1, v2 )
 
//	COMPUTE BARYCENTRIC COORDINATES
	var invDenom:Number	= 1 / ( dot00 * dot11 - dot01 * dot01 )
	var u:Number 		= ( dot11 * dot02 - dot01 * dot12 ) * invDenom
	var v:Number 		= ( dot00 * dot12 - dot01 * dot02 ) * invDenom
 
//	Check if point is in triangle
	return (u > 0) && (v > 0) && (u + v < 1)
   }

I managed to find this and another technique of calculating whether a point was in a triangle and that can be found here. There is a nice little example on the site showing you how the calculations work. I also managed to find some nice little tips for speeding up Math calculations in Flash by using bitwise maths which I found on labs.polygonal.de. The Math.abs function was one of the most improved and helped speed things up.

   static public function abs( x:Number ):Number
   {
	return (x ^ (x >> 31)) - (x >> 31);
   }

Another helpful tip Mark gave me was if you are making the same calculation over and over within the same class, then by declaring the Math function as a function, stops the Flash Player from continusly having to go and get that function. I was shocked at the difference it made.

   private var math_sin:Function = Math.sin
   math_sin( angle )

Leave a comment