Search code examples
c#xnacollision-detectionbreakout

ball reflection angles Xna c#


I'm trying to find a way to handle reflections for a breakout clone.

I would upload an image to the post instead of the following paragraph, however i have not yet gained the privilege of that yet.

If the ball intersects the left hand side i want it to bounce off to the left. if the ball intersects the right hand side i want it to bounce off to the right. if the ball intersects the middle section i want it to bounce up the way. i want to learn how to make it bounce in a varying direction dependant on what side of the left, right, or middle section was intersected

I would like to not use three separate rectangles for this, i want to learn how to do it with one.

I use a Vector2 for ball velocity, projVel.

It's position is projPos.

A rectangle for the paddle lightRect.

The reason I use proj.collRect for the beginning of the if is because I cannot use the intersect method with Vector2.

This is my makeshift collision handler at present, which does work but the speed changes to an extent which renders the game unplayable. The speed clamp i have only slightly slows it down i think. i have a variable for projSpeed i cannot clamp that or it will never be able to stop.

    if (proj.collRect.Intersects(lightSaber.lightRect))
    {
                proj.projPos.Y = lightSaber.lightRect.Y - proj.projTxr.Height;
                proj.projVel.Y *= -1;

        proj.projVel.X = 10 * (proj.projPos.X - lightSaber.lightRect.Center.X) / (lightSaber.lightRect.Center.X);
    }

            proj.projVel.X = Math.Max(-4, Math.Min(proj.projVel.X, 4));
            proj.projVel.Y = Math.Max(-4, Math.Min(proj.projVel.Y, 4));

Help me by showing me how I could do this, maybe in the Math. method, or even an alternative to .Intersects so I can use projPos instead of collRect.

I really am not sure where to start, if there is another way I could do it an example would be great.


Solution

  • Instead of manipulating X and Y velocities independently, I recommend that you calculate a reflection angle based on the position and then derive the velocity from the angle and the speed prior to impact.

    Example:

    // NOTE: this code assumes that positive Y is down
    if (proj.collRect.Intersects(lightSaber.lightRect) && projPos.projVel.Y > 0.0f) // only bounce if projectile is moving downward
    {
        // remember current speed for when we calculate new velocity
        var projSpeed = projVel.Length(); 
    
        // make sure the projectile no longer intersects the bar
        proj.projPos = lightRect.Y - proj.projTxr.Height;
    
        // interpolate reflection angle
        var t = (proj.projPos.X - lightSaber.lightRect.X) / lightSaber.lightRect.Width;
        var reflectDegrees = 150.0f - t * 120f; // straight up +/- 60 degrees
        var reflectRadians = reflectDegrees * (float)Math.PI / 180.0f;
    
        // final velocity determined by angle and original projectile speed
        proj.projVel = new Vector2((float)Math.Cos(reflectRadians) * projSpeed, -(float)Math.Sin(reflectRadians) * projSpeed);
    }