Border Collisions
I am making pong in java, everythig works but I can't seem to get collision detection
working, Everytime the ball "collides" with the borders, it just goes berserk, stays in
the border for a bit and the contiues on. All my other code works fine except border detection
and was wondering if anyone can give me sugggestions:
Here is my code:
if ((ballRect.x <= 0) || (ballRect.x >= frameRect.width - ballRect.width) || (ballRect.y <= 0) || (ballRect.y >= frameRect.height - ballRect.height))
{
// Do bouncing stuff ...
}
Well, It should be self explanatory
I only posted that part since I think it is the only problem in my code
[706 byte] By [
GniBa] at [2007-9-28 11:09:04]

You need to seperate out your "bouncy" logic.
if( (ballRect.x <= 0) || (ballRect.x >= frameRect.width - ballRect.width) )
{
ball_X_Velocity *= -1;
}
if( (ballRect.y <= 0) || (ballRect.y >= frameRect.height - ballRect.height) )
{
ball_Y_Velocity *= -1;
}
there are other ways, but this is the most straight forward.
Erm, isn't that just the same as I am doing but more spread out?
GniBa at 2007-7-12 1:30:32 >

does your bounce code multiply by more than -1.0 ? (e.g. -0.9)
if so, the return bounce will not always bounce the ball far enough back into the arena, hence the ball will collide with the boundary again, resulting in the ball sticking to the side)
The fix this, you should correction the balls position when it bounces.
heres some code that shows what 2 do (it will not be immediately obvious exactly how it works - but trust me - it does :P)
if(x<0) //left boundary check
{
x = -x;
dx*=-0.9;
}
else if(x>arenaWidth) //right boundary check
{
x = arenaWidth*2-x;
dx*=-0.9;
}
if(y<0) //top boundary check
{
y = -y;
dy*=-0.9;
}
else if(y>arenaHeight) //bottom boundary check
{
y = arenaHeight*2-y;
dy*=-0.9;
}
What exactly does dx supposed to be for?
GniBa at 2007-7-12 1:30:32 >

> What exactly does dx supposed to be for?dx=delta x :)in the mainloop you have usually something like this, to update the ball position:x+=dx;y+=dy;
oNyxa at 2007-7-12 1:30:32 >

I do it like that:
if(x<0 && dx<0){ //left boundary check
dx*=-1;
}
else if(x>arenaWidth && dx>0){ //right boundary check
dx*=-1;
}
if(y<0 && dy<0){ //top boundary check
dy*=-1;
}
else if(y>arenaHeight && dy>0){ //bottom boundary check
dy*=-1;
}
> I do it like that:
> if(x<0 && dx<0){ //left boundary check
>dx*=-1;
> }
> else if(x>arenaWidth && dx>0){ //right boundary check
>
>dx*=-1;
> }
>
>
> if(y<0 && dy<0){ //top boundary check
>dy*=-1;
> }
> else if(y>arenaHeight && dy>0){ //bottom boundary
> check
>dy*=-1;
> }
That works fine if you have no friction.
However, if you changed your code, so it was something like dy*=-0.9
(a 10% friction) your ball, when it came to bounce back, wouldn't bounce back as far as it initially travelled.
This would occasionally result in the ball getting stuck in the side wall.
It would also mean when a ball collides with the side of the arena, it would momentarily be outside the legal bounds of the arena. (this might cause problems elsewhere in your code [if you had ever assumed the ball would always be inside the arena])
My code fixes that problem, by moving the ball back into the arena as if it had bounced.
For instance,
If a ball hit the left side, and went to a position of -4, my code would correct the balls position to +4, and would then apply the necessary changes to the dx.
Infact, even doing this is incorrect, as I am applying the pre-bounce dx for a small portion of time after the bounce.
For it to be truely accurate, you would have to break the bounce into 2 parts, the pre-bounce and the post-bounce. The pre-bounce would use the initial dx value, the post-bounce would use the new modified dx value.
all that just to simulate a simple bounce :S
oh the joys of using discrete simulation to model continuous systems :P
pretty much... your trying to test for 2 directions at once...
when your if evaluates to true how do you know if you have hit a horizontal or a vertical border?
my guess: your multiplying both by -1... or something. maybe if you show the code inside the if I could understand.
The way I like to handle collisions, is to not only ensure that two objects are close enough to collide, but that they are moving in the correct direction to collide.
So, if ball.x < 0 and ball.velocityX < 0 then initiate collision. This method works well for collisions of 2 balls too.
Of course with 2 balls colliding, the math is a little more complicated.
Also, things might be easier if you work with vectors. The code below is old and so I wouldn't take it as good coding style, but it contains the correct mathematics for handling collisions with walls and with other objects.
I have a class V2, which is just 2 double variables x and y. I also have a class Phase, which is a V2 for position, x and a V2 for velocity v. It's rather unfortunate that I called the position variable x
// Walls
if ((bean.phase().x().x() > surface.getWidth() - bean.getWidth() && bean.phase().v().x() > 0) ||
(bean.phase().x().x() < 0 && bean.phase().v().x() < 0))
bean.phase().v(new V2(-bean.phase().v().x(),bean.phase().v().y()));
if ((bean.phase().x().y() > surface.getHeight() - bean.getHeight() && bean.phase().v().y() > 0) ||
(bean.phase().x().y() < 0 && bean.phase().v().y() < 0))
bean.phase().v(new V2(bean.phase().v().x(),-bean.phase().v().y()));
// Other Parts
for (int j=i+1;j<beans.size();j++) {
Bean other = (Bean)beans.get(j);
V2 iC = bean.getCenter();
V2 jC = other.getCenter();
if (iC.sub(jC).len() ><= bean.getRadius() + other.getRadius()) {
double ma = bean.phase().v().dot(jC.sub(iC).unit());
double mb = other.phase().v().dot(iC.sub(jC).unit());
V2 a = jC.sub(iC).unit().mul(ma);
V2 b = iC.sub(jC).unit().mul(mb);
if ((ma > 0 && ma > -mb) || (mb > 0 && mb > -ma)) {
double iM = bean.getMass();
double jM = other.getMass();
bean.phase().v(bean.phase().v().add(a.neg().add(b.mul(2*jM).add(a.mul(iM-jM)).div(iM+jM))));
other.phase().v(other.phase().v().add(b.neg().add(a.mul(2*iM).add(b.mul(jM-iM)).div(iM+jM))));
}
}
}
