Hi!


Concerning the trigonometry applied to Actionscript 3.0, last time we have seen how to control collisions and bouncing on angled surfaces.

Since the reported example was on an unique surface, in this tutorial we will see how to use the same trigonometric formulas applied to more angled surfaces.

In substance it doesn't change very much, the used formulas are always the two seen first:


rotation of the coordinates of the system:


Code:
x1=Math.cos(angle)*xx-Math.sin(angle)*yy;
y1=Math.cos(angle)*yy+Math.sin(angle)*xx;
bring back the coordinate to their initial state:
Code:
x1=Math.cos(angle)*xx+Math.sin(angle)*yy;
y1=Math.cos(angle)*yy-Math.sin(angle)*xx;











I create a FLA and I save it as ' trigonometria7.fla '.
Into which, I draw an horizontal line, I convert it into a MovieClip and I name it mc_line.
I instantiate it 7 times on stage and I assign to the them the respective instance names: line_0_mc, line_1_mc, line_2_mc, line_3_mc, line_4_mc, line_5_mc, line_6_mc .
Next, I create another MovieClip of circular shape as if it was a ball and I assign to it the instance name ball_mc.
Then, I create another level, I open the Action Panel and I write:
Code:
var lines_array:Array=new Array(line_0_mc,line_1_mc,line_2_mc,line_3_mc,line_4_mc,line_5_mc,line_6_mc);
lines_array[0].rotation=30;
lines_array[1].rotation=-20;
lines_array[2].rotation=-10;
lines_array[3].rotation=40;
lines_array[4].rotation=-30;
lines_array[6].rotation=30;

var vx:Number=0;
var vy:Number=0;
const GRAVITY:Number=.5;
const BOUNCE:Number=-.7;

addEventListener(Event.ENTER_FRAME,moveball);

function moveball(evt:Event):void
{
	vy+=GRAVITY;
	ball_mc.x+=vx;
	ball_mc.y+=vy;
	
	checkFloor();
	for(var i:int=0;i < lines_array.length;i++)
	{
		checkCollisions(lines_array[i]);
	}
}

function checkFloor():void
{
	if(ball_mc.y+ball_mc.height/2>stage.stageHeight)
	{
		ball_mc.y=stage.stageHeight-ball_mc.height/2;
		vy*=BOUNCE;
	}
}

function checkCollisions(m:MovieClip):void
{
	var bounds:Rectangle=m.getBounds(this);
	if(ball_mc.x > bounds.left &&ball_mc.x < bounds.right)
	{
		var angle:Number=m.rotation*Math.PI/180;
		var cosine:Number=Math.cos(angle);
		var sine:Number=Math.sin(angle);

		var x1:Number=ball_mc.x-m.x;
		var y1:Number=ball_mc.y-m.y;

		var y2:Number=cosine*y1-sine*x1;

		var vy1:Number=cosine*vy-sine*vx;

		if(y2 > -ball_mc.height/2&&y2 < vy1)
		{
			var x2:Number=cosine*x1+sine*y1;
			
			var vx1:Number=cosine*vx+sine*vy;
		
			y2=-ball_mc.height / 2;
			vy1*=BOUNCE;
			
			x1=cosine*x2-sine*y2;
			y1=cosine*y2+sine*x2;
			vx=cosine*vx1-sine*vy1;
			vy=cosine*vy1+sine*vx1;
			ball_mc.x=m.x+x1;
			ball_mc.y=m.y+y1;
		}
	}
}

Let us analyse the code:


I create an Array into which I insert every instance name of the MovieClip placed on stage

var lines_array:Array=new Array(line_0_mc,line_1_mc,line_2_mc,line_3_mc,line _4_mc,line_5_mc,line_6_mc);

I assign a rotation to each line

lines_array[0].rotation=30;

lines_array[1].rotation=-20;

lines_array[2].rotation=-10;

lines_array[3].rotation=40;

lines_array[4].rotation=-30;

lines_array[6].rotation=30;


I create 2 variables into which I insert the values of the x and y speed

var vx:Number=0;

var vy:Number=0;

a constant that contains the value of gravity

const GRAVITY:Number=.5;

a constant that contains the value of bouncing height

const BOUNCE:Number=-.7;


I add an ENTER_FRAME that calls the function moveBall

addEventListener(Event.ENTER_FRAME,moveBall);


In the function moveBall:

I increase progressively the speed on the y axis of ball_mc adding the constant GRAVITY

vy+=GRAVITY;

I pass to the properties x and y, the values of the speed (vx and vy)

ball_mc.x+=vx;

ball_mc.y+=vy;

I call the function checkFloor that will check if ball_mc collides with the maximum height of the stage (as if it was the floor)

checkFloor();

Into a for cycle, I continuously call the function checkCollisions passing to it, as parameter, each MovieClip container in the array (the lines)

for(var i:int=0;i < lines_array.length;i++)

{

checkCollisions(lines_array[i]);

}


In the function checkFloor:

I continuously check if ball_mc collides with the lowest part of the SWF using the same technique explained in the tutorial about the bouncing ball.

if(ball_mc.y+ball_mc.height/2>stage.stageHeight)

{

ball_mc.y=stage.stageHeight-ball_mc.height/2;

vy*=BOUNCE;

}


In the function checkCollisions I use the same technique explained in the precedent tutorial: trigonometry example 7 other then for the 2 lines in which I use the method getBounds():

I create a variable of type Rectangle and I assign to it the value returned by the method getBounds applied to the line being checked.

In concrete, this method returns a rectangle that has the x, y, width and height of m (the line being checked).

Then, using an if, I check that the x of ball_mc is bigger then the maximum left area of the rectangle of the line being checked and smaller then the maximum right area of the rectangle of the line being checked.

If you try to remove this check, you will better understand the use of it.


All the rest, as said before, as already been explained.

var bounds:Rectangle=m.getBounds(this);

if(ball_mc.x > bounds.left &&ball_mc.x < bounds.right)

{

var angle:Number=m.rotation*Math.PI/180;

var cosine:Number=Math.cos(angle);

var sine:Number=Math.sin(angle);


var x1:Number=ball_mc.x-m.x;

var y1:Number=ball_mc.y-m.y;


var y2:Number=cosine*y1-sine*x1;


var vy1:Number=cosine*vy-sine*vx;


if(y2 > -ball_mc.height/2&&y2 < vy1)

{

var x2:Number=cosine*x1+sine*y1;


var vx1:Number=cosine*vx+sine*vy;


y2=-ball_mc.height / 2;

vy1*=BOUNCE;


x1=cosine*x2-sine*y2;

y1=cosine*y2+sine*x2;

vx=cosine*vx1-sine*vy1;

vy=cosine*vy1+sine*vx1;

ball_mc.x=m.x+x1;

ball_mc.y=m.y+y1;

}

}


See you soon!