0
votes

I have been working on and off of a certain game I'm making (trying to get it finished!) and a problem that has been unsolved for a while in it is the collision detection between a ball and a square.

Basically what I want to happen eventually is depending on the angle/way the rectangle is facing, I want the ball to bounce of it accordingly (I know I could just inverse the ball direction before/as it hit the square).

At the moment though, my current problem is trying to inverse the correct X and Y components depending on the side/face that the ball collides with the square, e.g. if the ball hits the right side of the square, then I need to inverse the ball's X component.

This doesn't seem to work and I was wondering if I could somehow label each side of the rectangle, in terms of for the top of it label that 'face 1' or something, then for the right side of it 'face 2' or 'side 2', etc...

I have provided some code below (this is the code I'm using now):

//(collision with right side of square)
if (theBall.GetRectangle.Left <= thePaddle.GetRectangle.Right)
{
    theBall.pVelocity.X = -theBall.pVelocity.X;
}

//(collision with bottom of square)
if (theBall.GetRectangle.Top <= thePaddle.GetRectangle.Bottom)
{
    theBall.pVelocity.Y = -theBall.pVelocity.Y;
}

I have written the code for the other 2 sides of the rectangle but they are just the opposite of the two above, i.e. for collision with top of rectangle = opposite of bottom, etc.

EDIT: the object I am checking against if the ball has collided with DOES NOT move, I mean it only rotates... so I don't know if this is important (it probably is, therefore I apologise for missing this info out at the start).

EDIT @ 23:36: ok, I have tried something.... and it hasn't worked... :(

public Vector2 DistBetweenBallAndBlock(Paddle thePaddle, Ball theBall)
    {
        Vector2 centreOfBall = new Vector2(theBall.Texture.Width / 2, theBall.Texture.Height / 2);

        float distX = thePaddle.Position.X - centreOfBall.X;
        float distY = thePaddle.Position.Y - centreOfBall.Y;

        if (distX < 0)
        {
            distX = -distX;
        }

        if (distY < 0)
        {
            distY = -distY;
        }


        return new Vector2(distX, distY);
    }

I have then tried to just print the result just to get an idea of what's going on and what sort of values are being output:

Vector2 a = ball.DistBetweenBallAndBlock(paddle1, ball);            
        angleOfPaddle = Math.Atan2(a.Y, a.X);

I then just print this value to screen, however I am getting the same result of 0.63...

2
Are you for some reason not using purely radius based collision for the ball? It's rather nice to only worry about distance for circular objects.Magus
Nope im not. I sort of know what you mean but i don't really know the sort of code to write for it...6a6179
Essentially, you create a vector between the center of the ball and the nearest point on the object you're checking against, and if it's length is below the radius of the circle, there's a collision. Getting the nearest point is more difficult, but you'd probably do it by finding the two nearest corners and then finding the closest point along them. Now I feel like looking up vector formulas :DMagus

2 Answers

1
votes

To detect a collision between Rectangles you could use Rectangle.Intersect method, instead of checking the objects' sides.

And to detect which side of the rectangle is hit, you can compute the Vector2 between the ball center and the rectangle center. Getting its angle with Math.Atan2 you can easily know which face of the rectangle has been hit.

0
votes

Looked up some Vector stuff, based on my comment.

Collision Style

The optimal way of colliding with a circular object is to collide using a vector between it and the nearest point of the object you're checking against. If the distance is less than or equal to the radius of the circle, there is a collision. The advantages of this method are that you don't have to keep track of a rectangle, you get circular collision, and you get the angle of the collision from the vector.

How You Do It

I'll assume you have some strategy to keep from considering every object every frame, and keep to the basic problem. Your paddle has 4 vertices, one for each corner. Because your ball is essentially a vertex with a picture drawn over it, you can easily check the distance between the ball and each corner of your paddle. Two will be nearest. From there, it's just a matter of finding out if that edge collides. I found a solution to that here, which includes a nice formula.

Does that help?