Breakout Collision pt. 2

Started by
7 comments, last by NotAYakk 17 years, 7 months ago
Alright, as seen by my prototype in the announcements forums my collision detection works perfectly 100% of the time on collisions between a ball and a static brick. I do line-tests so the ball can accelerate to ridiculous speeds and still have pixel perfect collisions. However, when applied to the paddle, this procedure fails. Simply testing the paddle's current position obviously does not work because it can move inside of a ball between frames. I tried to improve this by following a similar procedure to my ball-ball collision detection, the procedure of which is found here. http://www.gamasutra.com/features/20020118/vandenhuevel_pfv.htm -I get the vector from the paddle's last to current position -I subtract the vector of the paddle from the vector of the ball to get the relative motion between the two -I test the updated ball using the static collision test from before (no bugs there, damn positive) -I add the velocity of the paddle to the velocity of the ball so the ball will "drag" along the paddle However, there is something wrong somewhere down the line, as the paddle can pass through the ball still. The problem is not with my collision response, as when the paddle passes through the ball, it does not turn the ball blue (if that doesnt maks sense and you're curious, play my prototype) An alternative or improvement on this method would be appreciated, as I'm pretty stuck here and this is the 2nd to last major bugfix.
Advertisement
I would do the ball line test, against the 'swept paddle', basically rather than test the ball against the paddle's current position or previous position, create a longer 'swept paddle' that cover's the area traced out as the paddle moved between the two locations.
might make you get some false results at either edge, but at high update rate who's going to notice, they'd be false positives anyway so you're giving the player the benefit of the doubt.


really though... as long as the paddle isn't moving very fast (usually not) there should be no issue with doing the simple test against the ball line and its current location each time...
There might be some other bug...
PS
is your paddle connected to the mouse cursor?
you might want to limit the speed of the paddle so that players who set their mouse to higher sensitivity/speed dont get an advantage with paddle movement speed...
rather than have the paddle match the cursor, only have it try to follow it around, but maintain speed limits

this might also help with balls missing high speed paddles...
Quote:-I get the vector from the paddle's last to current position
-I subtract the vector of the paddle from the vector of the ball to get the relative motion between the two
-I test the updated ball using the static collision test from before (no bugs there, damn positive)
-I add the velocity of the paddle to the velocity of the ball so the ball will "drag" along the paddle


P_loc0 and P_loc1 are paddle old and new velocity.
B_loc0 and B_loc1 are the old and new position of the ball.

Define P_v0 := P_loc1-P_loc0
Define B_v0 := B_loc1-B_loc0

Define B_v1 := B_v0+P_v0

Does the Ball or the Paddle collide between time 0 and time 1?

Yes, if and only if a ball at
B_loc0 + t*B_v1
collides with the paddle at P_loc0 for some t in the closed interval [0,1]

...

Now, there are alot of subtle ways you could almost implement the above, but not quite. Does what I describe match up exactly with what you implemented? Is it close? How is it different?
Quote:Original post by Anonymous Poster
I would do the ball line test, against the 'swept paddle', basically rather than test the ball against the paddle's current position or previous position, create a longer 'swept paddle' that cover's the area traced out as the paddle moved between the two locations.
might make you get some false results at either edge, but at high update rate who's going to notice, they'd be false positives anyway so you're giving the player the benefit of the doubt.


really though... as long as the paddle isn't moving very fast (usually not) there should be no issue with doing the simple test against the ball line and its current location each time...
There might be some other bug...



I've tried testing the ball against the swept paddle, didn't see any change at all, especially not false positives. Tried again per your suggestion, same result. The paddle is tied to the cursor, tried setting a max speed, but showed no improvement even at ridiculously low speeds. It doesn't pass through the ball ALWAYS when the paddle is moving, but the majority of the time it does.
I don't imagine the bug is elsewhere, as the ball is not changing to the color of the paddle it hits, thus no collision detected. The only other place there could be a bug is the ball-block collision routine, but that is doubtful because that has NEVER failed to my observation in the maps I've played. I'll address post #3 when I can, as I'm packing to move to orlando tomorrow. Any more ideas, feel free to post 'em. Thanks for the replies.
Quote:Original post by NotAYakk
Quote:-I get the vector from the paddle's last to current position
-I subtract the vector of the paddle from the vector of the ball to get the relative motion between the two
-I test the updated ball using the static collision test from before (no bugs there, damn positive)
-I add the velocity of the paddle to the velocity of the ball so the ball will "drag" along the paddle


P_loc0 and P_loc1 are paddle old and new velocity.
B_loc0 and B_loc1 are the old and new position of the ball.

Define P_v0 := P_loc1-P_loc0
Define B_v0 := B_loc1-B_loc0

Define B_v1 := B_v0+P_v0

Does the Ball or the Paddle collide between time 0 and time 1?

Yes, if and only if a ball at
B_loc0 + t*B_v1
collides with the paddle at P_loc0 for some t in the closed interval [0,1]

...

Now, there are alot of subtle ways you could almost implement the above, but not quite. Does what I describe match up exactly with what you implemented? Is it close? How is it different?



Okay, lets see.
1)The paddle vector is correct. The ball vector is not obtained by subtracting current and last positions, but is a stored variable in the ball struct. No problems there. Basics accounted for.

2)My swept paddle test. I'm going to leave that as the default paddle-collision test. This seems to be correct, as I'm drawing the expanded paddle, and there is a "trail" behind the paddle that appears correct.
My expanded paddle is centered at the average x value of the last and current paddle position. The width is the width of the paddle plus the absolute value of the distance from the center to the adjusted center, eg. one point to the center. Before anyone asks, the width is from the center to one side, and is one half the total width.

paddlexex= (bluepaddlelast.x + bluepaddle.x //+ (bluepaddle.x + PaddleBall.xVec)/2;

paddlewidthex=bluepaddle.width +
abs((bluepaddle.x)- paddlexex);

cBall = objectCollision(pcBall, paddlexex, bluepaddle.y,paddlewidthex,bluepaddle.height);

I don't know if this is the "standard" way of doing it but it seems reasonable to me. No problems there.


3)What I had at the time of my last posting was the following

-Paddle and Ball Vectors acquired in the main game loop.

-I subtract the vector of the paddle from the vector of the ball to get the relative motion between the two.
I made a temporary ball variable here called pcBall for this purpose.

pcBall = cBall; //sets it equal to the ball passed to the collision func
pcBall.xVec = pcBall.xVec - PaddleBall.xVec;
pcBall.yVec = pcBall.yVec - PaddleBall.yVec;

-I test the updated ball using the static collision test from before (no bugs there, damn positive)

//cBall = objectCollision(pcBall, bluepaddle.x, bluepaddle.y,bluepaddle.width,bluepaddle.height);

For good measure, here's the paddle update code in the gameloop. moveamount is the variable where the x coordinate of the mouse is stored in the WM_MOUSEMOVE statement. I added time basing to the paddle movement today though, because I like the way the paddle moves after doing so. Seems to "glide" more and feels less like a cursor.

PaddleBall.xVec = moveamount - bluepaddle.x;
bluepaddlelast.x = bluepaddle.x;
bluepaddle.x = bluepaddle.x + PaddleBall.xVec*rTime;
if(bluepaddle.x+bluepaddle.width > MAPBARRIER){bluepaddle.x = MAPBARRIER-bluepaddle.width;}
if(bluepaddle.x-bluepaddle.width < 0){bluepaddle.x = 0+bluepaddle.width;}


If I'm not misinterpreting your post, here's what I have now, matching up.
pcBall = cBall;

Define B_v1 := B_v0+P_v0
pcBall.xVec = pcBall.xVec + PaddleBall.xVec;
pcBall.yVec = pcBall.yVec + PaddleBall.yVec;


Does the Ball or the Paddle collide between time 0 and time 1?

Yes, if and only if a ball at
B_loc0 + t*B_v1
collides with the paddle at P_loc0 for some t in the closed interval [0,1]


pcBall.xVec = pcBall.xVec + PaddleBall.xVec;
pcBall.yVec = pcBall.yVec + PaddleBall.yVec;
pcBall.x = pcBall.lx +pcBall.xVec*rTime;
pcBall.y = pcBall.ly +pcBall.yVec*rTime;

rTime being the time elapsed between frames, and lx and ly being the last positions of the ball.

Finally, I test the collision
cBall = objectCollision(cBall, paddlexex, bluepaddle.y,paddlewidthex,bluepaddle.height);


If this is correct, it still fails to work. I've tried about half a dozen modifications of my original procedure, and I seem to observe some slight improvement, but that could simply be because I move the mouse differently each time.

Any corrections or ideas would be greatly appreciated ;)
No one? Is there something I can do to help root out the problem?
Is my formula correct and the bug somehow lies elsewhere? Can someone at least point me to some articles? I've been stuck on this for a while now...
Would a demo of the problem help?
Here's one.
Just bounce the small ball out of the way and run the paddle through the big one.
well, if the collision funciton works
and the theory sounds good
then maybe it's just a dumb logic bug someplace in your code, a typo or something
maybe a mistake in your math at a point

having a sphere collide with a rectangle really should be a simple matter
you might just keep it simple, and code a special ball/paddle collision function from scratch (toss out whatever is going wrong now)
that would take what? 10 mins to write a new one? sphere vs rectangle function...
Quote:1)The paddle vector is correct. The ball vector is not obtained by subtracting current and last positions, but is a stored variable in the ball struct. No problems there. Basics accounted for.


Is your ball vector accurate?

Are you doing a collision test between where the paddle HAS BEEN and where the ball WILL BE?

When you collide with a non-moving target, do you use the SAME EXACT code path (except the old position equals the new position), or do you run DIFFERENT code? If so, then fix this.

Quote:My swept paddle test. I'm going to leave that as the default paddle-collision test. This seems to be correct, as I'm drawing the expanded paddle, and there is a "trail" behind the paddle that appears correct.
My expanded paddle is centered at the average x value of the last and current paddle position. The width is the width of the paddle plus the absolute value of the distance from the center to the adjusted center, eg. one point to the center. Before anyone asks, the width is from the center to one side, and is one half the total width.


I see no need for the gynmastics you are doing above at all.

The paddle is at location X0, with width W.

The paddle, at the last time you checked collision, was at location X1.

Where in the world did the "expanded paddle" talk come from? The paddle has a width. You can translate the velocity of all other objects by the movement of the paddle since the last collision test, and you now have a frame of reference in which the paddle is stationary and has a fixed width.

Next, your code is far far too tied to your game logic. You shouldn't be colliding THE BALL and THE PADDLE -- you should take the data from THE BALL and THE PADDLE and testing if they collide, as arbitrary things.

This allows you to detach the testing of the collision from the testing of the ball/paddle code. You can test the collision code (on moving targets!) first. Then you can hook up the ball/paddle to the collision code, and test just the connection, not both at the same time.

This topic is closed to new replies.

Advertisement