I've kept you waiting long enough. Here's the real stuff: bouncing off sloped walls. A quick reminder: in order to calculate the new speed vector, we split up the old speed vector in a component perpendicular to the wall and a component parallel to the wall. We flip the perpendicular component, add this to the parallel component and get the new speed vector. To stick with mathematical terminology we'll call the "perpendicular" component the "normal" component and the "parallel" component the "tangential" component.
Step 1 First we split up the speed vector in a normal and a tangential component. In other words we project the speed vector onto the N and the T axis. We get the value of vn by taking the dot product of the vectors v and N and the value of vt by taking the dot product of the vectors v and T.
Step 2 In order to get the new speed vector after bouncing, we flip the normal component of the speed vector and keep the tangential component. Putting them together again, gives us the new speed vector.
Step 3 Unfortunately the new speed vector v is a vector in the NT co-ordinate system. This is not useful as such, because we're programming in the XY co-ordinate system. So what we need to do is rotate the NT co-ordinate system to match the XY co-ordinate system. When reading about 2D rotation you'll often see the formulas: x' = y * sin (a) + x * cos(a) y' = y * cos(a) - x * sin(a) or in matrix form | cos a sin a | [x' y'] = [x y] | | | -son a cos a |
We're going to do exactly the same here, but with vectors and dot products instead of angles and trigonometry. We cannot project v onto the X and Y axis directly, because v is in NT co-ordinates. But we can split up vt and vn in X and Y components. This gives us 4 components: vnx, vny and vtx and vty. The sum of vnx and vtx gives us the X component of v and the sum of vny and vty gives us the Y component of v.
Step 3 bis Confused? Let's move the vectors vnx, vny, vtx, vty to a position that is more clear. You see? vnx + vtx = the X-component of v and vty + vny = the Y-component of v.
And now the good news. All this theory can be expressed in 9 lines of actionscript:
private function move (x:Number, y:Number, speedVec:Vector) { ... for (var i=0; i<this.walls.length; i++){ ... } if (bestResultObj != undefined) { ... // get N and T component of speed vector, invert tangential component var wallVec = this.walls[bestResultObj.wallIdx].v.getNormalized(); var wallNormal = this.walls[bestResultObj.wallIdx].n; var t = wallVec.dot(this.v); // magnitude of the tangential component var n = wallNormal.dot(this.v); // magnitude of the normal component
// turn into a vector again by multiplying the magnitude with // the tangential and the (flipped) normal direction var vt = wallVec.cross(t); var vn = wallNormal.cross(-n);
// project <vt, vn> onto x-y axis // x-axis = new Vector(1, 0) , y-axis = new Vector(0, 1) var vx = new Vector(1, 0).dot(vn) + new Vector(1, 0).dot(vt); var vy = new Vector(0, 1).dot(vn) + new Vector(0, 1).dot(vt);
We're almost through. Here is a demo of what we have so far. One more bug will be covered on the next page, but it is unlikely that you will encounter it here.
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