Johan van Mol .org
HomeHome
ArticlesArticles
BlogBlog
Advanced SearchAdvanced Search
Home arrow Articles arrow Flash arrow Collision detection & bouncing part 3: bouncing balls
Collision detection & bouncing part 3: bouncing balls Print E-mail
Sunday, 10 September 2006
Article Index
Collision detection & bouncing part 3: bouncing balls
More about the dot product
demo 1: basic bouncing
demo 2: finding the closest wall
demo 3: recursive collision detection
demo4: rethinking the algorithm
demo5: bouncing off sloped walls
demo6: the last bug

demo6: the last bug

We have one more bug. Check the demo below.


This bug hardly shows up, but when I see one, I won't rest until I've killed it. For software bugs that is, I'm a little more tolerant towards real bugs (except the ones that suck blood).
So I've been staring at the code for hours, tracing thousands of lines and stepping multiple times through every single line of code with the debugger to find out that I made a beginner's mistake.
The co-ordinates I'm putting the ball in have a high precision: e.g. x = 152.2547, y = 358.9987. But Flash MovieClip co-ordinates have a much lower precision: 0.05 pixels is the lowest possible increment.
So I think I'm putting the ball in position (152.2547, 358.9987), but Flash puts in (152.25, 358.95) which happens to be a fraction of a pixel outside the wall, which makes it will fly through.

Instead of relying on the MovieClip's _x and _y values, we define two more variables:
private var ballX:Number;       // ball's x-coor
private var ballY:Number;       // ball's y-coor

The only function that changes is the step() function. We'll use ballX and ballY in all the calculations and at the end of the code we set _x to ballX and _y to ballY.

public function step() {
    if (this.bPlaying) {
        // the precision of a movieclip's _x and _y is limited, therefore we store the
        // exact position in this.ballX and this.ballY
        var o = this.move(this.ballX, this.ballY, new Vector(this.v.x, this.v.y));
        this.ballX = o.x;
        this.ballY = o.y;
        this.ball_mc._x = this.ballX;
        this.ball_mc._y = this.ballY;
    }
}


Download all demos' source code as zip | view this demo's source code in a new window

And that's it, we're done.
Keep in mind that the algorithm covered here has a limitation, it won't work with concave polygons in all cases. Concave polygons are polygons that have corners pointing inwards.

Now as an exercise develop a pinball game and let me know how it worked out ;-)


Comments
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


 1 
Page 1 of 1 ( 6 comments )
©2005 MosCom

You are not authorized to leave comments - please login.