In some cases the ball will fly through the wall. Check this movie:
The problem is actually twofold: the ball goes trough the wall, but it also bounces in the wrong direction. This is hard to see in the flash movie, but the horizontal wall is hit first, so you would expect the ball the bounce up (the green line in the figure). But it bounces off the vertical wall to the left (the red line). Let's tackle this problem first. To detect a collision we loop through the list of walls, as soon as a collision is detected we break the loop. So the ball will bounce as a result of the first collision encountered. But in this case the collision with the 3rd wall from the list (the horizontal wall) occurs before the collision with the 2nd wall (the vertical wall). We can use the t value returned by the checkCollision() function to determine which collision will happen first. The smaller the t value, the closer the ball is to the collision point. In order to solve this problem we'll change the step() function. If the result of the checkCollision() function is not -1, when we have a collision, we create an object in which we store the result and the index of the wall. If this is the first result object, it is obviously also the best, so we also store it in the variable bestResultObj. If bestResultObj is defined already, we compare the last result with the best result and store the best (smallest isectRatio) in bestResultObj. After looping through the walls list we handle the collision with the parameters defined in bestResultObj.
// collision detection var bestResultObj; var resultObj; for (var i=0; i<this.walls.length; i++){ ... var result = checkCollision({x: pt.x, y: pt.y}, this.v, {x:this.walls[i].x, y:this.walls[i].y}, this.walls[i].v) if ( result != -1 ) { // create an object containing the portion of the // line segment traveled before the collision // and the index of the wall resultObj = new Object(); resultObj.isectRatio = result; resultObj.wallIdx = i; // find out the closest match. This is the one with the lowest isectRatio if (bestResultObj == undefined) { bestResultObj = resultObj; } else { if (resultObj.isectRatio < bestResultObj.isectRatio) { bestResultObj = resultObj; } } } }
if (bestResultObj != undefined) { // do all the bouncing stuff ... }
This doesn't prevent the ball from flying through the wall, but at least if flies through the right wall.
Its a gr8 tutorial for how can we use vectors instead of trigonometry for motions and collisions
Posted by poonam sheth, Whose homepage is http://smspoonam.blogspot.com on Wednesday, 11 October 2006 at 10:17
There's a typo on step 3bis:
...the Y-component of Y...
instead of
...the Y-component of v...
but great work ;).
Posted by Fugus, on Thursday, 19 October 2006 at 12:47
I fixed the typo. Thanx.
Posted by Johan van Mol, on Thursday, 19 October 2006 at 3:06
Thanks for the great set of tutorials, very helpful!
One issue I've been trying to solve is dealing with walls that the ball can hit from either side. The direction of the normal throws things off. What I did was added an else after the 'if (this.walls[i].n.dot(speedVec) < 0) { ' block in move().
Instead of var vec:Vector = this.walls[i].n.getInverted().cross(this.radius); in the else I have it as var vec:Vector = this.walls[i].n.cross(this.radius);
This seems to work, but I'm worried I've recreated the bugs you addressed in demo4, and I'm guessing there might be a better solution out there.
Posted by peter, Whose homepage is http://www.thup.com/ on Thursday, 07 December 2006 at 11:17
do you got a tool to convert a drawed wallshape to this wall array that needed?
Posted by Peter, Whose homepage is http://index.hu on Wednesday, 30 May 2007 at 4:03
First I draw the shape in Illustrator and save the file in Illustrator 8 format. Open the file in a text editor, scroll to the bottom and you'll find something like
(Layer 1) Ln
... more stuff here ...
24 803 m
69 828 l
108 775 l
31 757 l
24 803 l
The numbers in front are the X and Y coordinates. 'm' means moveTo, 'l' means lineTo. I copy and paste these codes, save them as a string in actionscript and parse the string.
Posted by Johan van Mol, on Wednesday, 30 May 2007 at 5:20