Problem with ball bouncing off wall

This topic is 4883 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hello folks! I have a problem with a ball bouncing off a wall. The problem seems to be with my do/while loop. If I use the loop the entire game freezes when the ball find a collision. changeDirection should be activated when we have found a collision (timeCollision != 1.0f). This function should move the ball so it intesects with the wall and find the new velocity of the ball. Then this procedure shuld be rerun (hence the do/while) to check if there is a collision based on the new velocity of the ball. If I don't use the do/while loop everything works fine, the ball bounces of the walls in the correct direction. But the problem with that is that the ball can jump past walls because I have no check on the new velocity. Can someone please help me? There is obviously something I have missed here
void Ball::move(Wall wall[4])
{
float timeCollision = 1.0f;

D3DXVECTOR2 normalCollision(0.0f, 0.0f); //Is used when we want to compute
// the ball bouncing off a wall
// or brick

D3DXVec2Normalize(&_direction, &_direction);//We want this length to be 1

D3DXVECTOR2 velocity = _direction * _speed; //Really, the vector from start
// position to end position

/////////////////////////////////////////////////////////////////////
do {
testBallHittingWall(wall, velocity, normalCollision,
timeCollision);

if(timeCollision != 1.0f)
{ changeDirection(velocity, normalCollision,
timeCollision); }

}while(timeCollision != 1.0f);
/////////////////////////////////////////////////////////////////////

_position += velocity;

D3DXMATRIX matMove;

D3DXMatrixTranslation(&matMove, _position.x, _position.y, 0.0f);

_d3dDevice->SetTransform(D3DTS_WORLD, &matMove);
}
//-----------------------------------------------------------------------------
void Ball::testBallHittingWall(Wall wall[4], D3DXVECTOR2& ballVelocity,
D3DXVECTOR2& planeNormal, float& hitTime)
{
hitTime = 1.0f;

//Check every wall
for(int i = 0; i < 4; i++)
{
//Find the point on the circle that first will come in contact with
// wall
D3DXVECTOR2 pointCircle = _position - (_radius * wall.normal);

//Compute the t value for the directed line ballVelocity intersecting
// the wall
float t = (wall.normalForm -
D3DXVec2Dot(&wall.normal, &pointCircle)) /
D3DXVec2Dot(&wall.normal, &ballVelocity);

//If t in [0..hitTime], save t in hitTime
if(t >= 0.0f && t <= hitTime)
{
hitTime  = t;
planeNormal = wall.normal;
}
}
}
//-----------------------------------------------------------------------------
void Ball::changeDirection(D3DXVECTOR2& ballVelocity,D3DXVECTOR2 planeNormal,
float hitTime)
{
//Move the ball so it intersects with the wall
_position += hitTime * ballVelocity;

//Here change the direction of the ball according to which wall it hit
if(planeNormal.x != 0.0f)
{ ballVelocity.x *= -1.0f; }
else //planeNormal.x == 0.0f
{ ballVelocity.y *= -1.0f; }

//Find the new velocity
ballVelocity = (1.0f - hitTime) * ballVelocity;

//Set the new direction
_direction = ballVelocity; //The direction is used the next frame
}



Share on other sites
In testBallHittingWall only test each wall if the dot product of the ball velocity and that wall normal is < 0

Share on other sites
There are two things you can do... both are quite common, including both at the same time.

First, you can push the ball out of the wall so that the collision is only detected once. This is usually achieved by detecting the collision depth and moving the ball that distance. You do already calculate this, you just aren't using it. It would be worth limiting the number of checks in your do while loop so that if the ball gets stuck between two walls ( a design issue ) the game continues, instead of hanging.

Secondly, you can check the velocity against the collision normal - don't just reverse the velocity. Your code assumes that the walls are always vertical or horizontal, so this is quite simple. Make sure that the normal of your wall is always pointing outwards (ie, in the direction in which the ball is allowed to exist) and then always make sure the velocity has the opposite sign before reversing it.

However, I see dot products and things in there, so why restrict yourself to axis-aligned walls? You are already using vectors! So stage 2 is the following, and allows diagonal walls:

A ball with velocity v hits a wall with normal n.
The magnitude of the velocity in the direction of n is m = v.n and if m > 0 the ball is travelling away from the wall and shouldn't bounce.
If it is bouncing, then the new velocity u will be the old velocity, modified by twice this component : u = v * (1 - 2 * m / |v|)

Share on other sites
Yes! It works!
Thanks alot.

Could you please explain me the difference between checking against this dot product and not doing it, MrRowl.

Share on other sites
Quote:
 Could you please explain me the difference between checking against this dot product and not doing it...
I believe the dot product MrRowl mentioned was simply to determine whether the ball is travelling toward the wall or away from it; if it is travelling away, you can skip the intersection test.

Share on other sites
OK. At least it seem to work, because the game does not freeze now after I have this check with this dotproduct. I will also check on the suggestion Squirm came up with.

1. 1
Rutin
37
2. 2
3. 3
4. 4
5. 5

• 11
• 10
• 13
• 103
• 11
• Forum Statistics

• Total Topics
632977
• Total Posts
3009673
• Who's Online (See full list)

There are no registered users currently online

×