Moving objects in flash using vectors - Collision
Written by Petar Jercic   
Article Index
Moving objects in flash using vectors
Collision
All Pages

Collision


The only thing left is hitting your balls against the wall. Now here is a great example of how to use the newly learned knowledge of vectors. We just have to know the direction and speed of the ball so when the ball bounces off the wall we just send it flying the same speed in different direction (alternatively you could slow the ball a little bit when it bounces to simulate losing speed in the bounce).


Wall collisions

What do we know so far? We can launch the ball in any direction using vector. We can limit the ball's speed to some desired value using normalization. Now let’s work out what happens when the ball hits the wall (it rhymes :).


Collision scenario

First (no. 1) we have the ball speeding towards the wall with some direction and speed. That information is contained inside the vector v=<7,-6>.

Second (no. 2) upon hitting the wall we have to reflect the incoming vector regarding axis the wall lies on. In example on the picture the wall lies on Y axis so we have to reflect vector's x – component from 7 to -7. And now we have a reflected vector. We are going to work with right angle walls so we don't have to calculate incoming angles, to make it simple. If the wall lies on Y axis, we just reflect (that just means reverse) x – component of the vector, and if it lies on X axis, we have to reflect y – component.

Third (no. 3), in the next iteration reflected vector will send the ball bouncing off the wall keeping it's angle of incidence.


Let's walk you through an example. We want to place a ball in the middle of the screen and make a vector that is tracing your mouse (red vector).We are also going to normalize that vector so you can see normalization in play (green vector). Of course we will normalize it further to some smaller value so the ball doesn’t rocket off screen before you can see it. When you click on the screen, the ball instance goes to array of all the balls on the screen. Then we move all the balls according to their direction vector. We don’t move the newly created ball in the middle of the screen.




Let's look at the code.


// init variables and attach ball object on screen
onLoad = function() {
	ballDepth = 100;
	balls = new Array();
	balls.push(attachMovie("ball", " ball_mc"+balls.length, ballDepth+balls.length, 
                               {_x:Stage.width/2, _y:Stage.height/2}));
}

First let's set some variables we will use later. Function onLoad runs only once at the start of the movie. Depth 'ballDepth' at which we will display the ball. Array ' balls' with all the balls currently on the screen. Finally we set the ball sitting in the middle of the screen, and we save its reference in the 'balls' array using push method. Push method just puts a given object in the array. Name of the instance " ball_mc"+balls.length has to be unique, so that’s why we use counter of the length of the array, “ball_mc1”, “ball_mc2”, “ball_mc3”, … . Depth "ballDepth+balls.length" has to be unique also, “101”, “102”, “103”, … .




// we draw vectors and move balls every screen
onEnterFrame = function() {
	clear();	// clear the screen
	
	// write last ball direction and add new ball
	if(Key.isDown(1)) {
		balls[balls.length-1].direction = vector2target;
		balls.push(attachMovie("ball", " ball_mc"+balls.length, ballDepth+balls.length, 
                                       {_x:Stage.width/2, _y:Stage.height/2}));
	}

Then every frame (iteration) we do the following. Function onEnterFrame runs once every frame. Clear the screen, which contains vectors drawn in the previous frame so we can draw new ones for this frame. Check if the user clicked on the screen (Key 1 is the left mouse button) and if he did, the magic happens. We assign last normalized vector2target vector to a ball instance that is in the middle of a screen waiting for your click, so it knows where and how fast to move. Then we put the new ball on the middle of the screen and in the array, waiting for your click patiently.




	//move all the balls except the new one withouth the direction
	for(var i=0; i<balls.length-1; i++) {
		//check if we hit the border and reverse the vector
		if(balls[i]._x < balls[i]._width/2 
                   || balls[i]._x > Stage.width-balls[i]._width/2)
			balls[i].direction.x = -balls[i].direction.x;

		if(balls[i]._y < balls[i]._height/2 
                   || balls[i]._y > Stage.height-balls[i]._height/2)
			balls[i].direction.y = -balls[i].direction.y;
		
		balls[i]._x += balls[i].direction.x;
		balls[i]._y += balls[i].direction.y;
	}

Then every ball in the array, that is on the screen, we move according to their direction vector assigned to them earlier. First we check if the ball hit the wall, and if it did, reverse the vector as explained before. For side (Y axis) walls we reverse x – component, balls[i].direction.x = -balls[i].direction.x;, and for the top/bottom (X axis) wall we reverse y – component, balls[i].direction.y = -balls[i].direction.y;. After that we just add x and y component of the direction vector to X and Y position of the ball, and the ball moves every iteration according to the direction and length (speed) of the direction vector.




	// vector from ball to cursor
	vector2target = 
        new Point(_root._xmouse-balls[balls.length-1]._x,
                  _root._ymouse-balls[balls.length-1]._y);
	drawLine("red", balls[balls.length-1]._x, balls[balls.length-1]._y, 
                  vector2target.x, vector2target.y);
	
	// normalize previous vector on fixed 50 units long
	vector2target.normalize(50);
	drawLine("green", balls[balls.length-1]._x, balls[balls.length-1]._y, 
                  vector2target.x, vector2target.y);
	
	// normalize to 5 units for moving the ball
	vector2target.normalize(5);
}

This part is the same as in the last example, drawing of the vector, and a normalized one form the ball in the middle of the screen to the mouse. And finally normalizing that vector to 5 units used for moving (direction vector) of the balls.



Full code is here:



import flash.geom.Point;

// init variables and attach ball object on screen
onLoad = function() {
	ballDepth = 100;
	balls = new Array();
	balls.push(attachMovie("ball", " ball_mc"+balls.length, ballDepth+balls.length, 
                               {_x:Stage.width/2, _y:Stage.height/2}));
}

// we draw vectors and move balls every screen
onEnterFrame = function() {
	clear();	// clear the screen
	
	// write last ball direction and add new ball
	if(Key.isDown(1)) {
		balls[balls.length-1].direction = vector2target;
		balls.push(attachMovie("ball", " ball_mc"+balls.length, ballDepth+balls.length, 
                                       {_x:Stage.width/2, _y:Stage.height/2}));
	}
	
	//move all the balls except the new one withouth the direction
	for(var i=0; i Stage.width-balls[i]._width/2)
			balls[i].direction.x = -balls[i].direction.x;

		if(balls[i]._y < balls[i]._height/2 
                   || balls[i]._y > Stage.height-balls[i]._height/2)
			balls[i].direction.y = -balls[i].direction.y;
		
		balls[i]._x += balls[i].direction.x;
		balls[i]._y += balls[i].direction.y;
	}

	// vector from ball to cursor
	vector2target = 
        new Point(_root._xmouse-balls[balls.length-1]._x,
                  _root._ymouse-balls[balls.length-1]._y);
	drawLine("red", balls[balls.length-1]._x, balls[balls.length-1]._y, 
                  vector2target.x, vector2target.y);
	
	// normalize previous vector on fixed 50 units long
	vector2target.normalize(50);
	drawLine("green", balls[balls.length-1]._x, balls[balls.length-1]._y, 
                  vector2target.x, vector2target.y);
	
	// normalize to 5 units for moving the ball
	vector2target.normalize(5);
}

// function for drawing lines, vectors
// specify color, start point, end point
drawLine = function(sColor, sX, sY, nX, nY){
	switch(sColor){
		case "red":
			color = 0xFF0000;
			break;
		case "blue":
			color = 0x0000FF;
			break;
		case "green":
			color = 0x00FF00;
			break;
		default:
			color = 0x000000;
			break;
	}
	lineStyle(2,color,100);
	moveTo(sX, sY);
	lineTo(sX + nX, sY + nY);
}

Marble box is a full blown game with this vector engine explained here, so check it out to see how it woks perfectly. Now you are ready to move your objects using vectors.


Thanks for reading this tutorial. I hope it helped.

Comments (0)