Jump to content
  • Advertisement
Sign in to follow this  
Azaykon

Problem with ball bouncing off wall

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

If you intended to correct an error in the post then please contact us.

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 this post


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

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!