Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Edit: My goal is to have it function like this:

Ball hits 1st Quarter = rebounds higher (aka Y++) Ball hits 2nd Quarter = rebounds higher (using random value) Ball hits 3rd Quarter = rebounds lower (using random value) Ball hits 4th Quarter = rebounds lower (aka Y--)

I'm currently using Rectangle Collision for my collision detection, and it's worked. Now I wish to expand it.

Instead of it simply detecting whether or not the paddle/ball intersect, I want to make it so that it can determine what section of the paddle gets hit. I wanted it in 4 parts, with each having a different reaction to impact.

My first thought is to base it on the Ball's Y position compared to the Paddle's Y position. But since I want it in 4 parts, I don't know how to do that.

So it's essentially be

if (ball.Y > Paddle.Y)
{
PaddleSection1 == true;
}

Except modified so that instead of being top half/bottom half, it's 1st Quarter, etc.

share|improve this question
1  
What's your goal? We can tell you how to use this tool of quarter-detection, but it may not be the best tool for your goal. For instance if you want to make the ball bounce in a different direction depending on the part of the bat hit, you would not determine the quarter. Instead you'd calculate the normal of the paddle where it's hit, perpendicular at the centre and closer to parallel when the ball hits closer to the side. This works fine on top of rectangle collision, whilst mathematically creating the illusion the rectangle is an ellipse (though only once it has collided with the rect). –  doppelgreener Jan 25 '11 at 3:44
    
Related to: gamedev.stackexchange.com/questions/7300/… –  bummzack Jan 25 '11 at 7:29
    
My goal is to have it function like this: Ball hits 1st Quarter = rebounds higher (aka Y++) Ball hits 2nd Quarter = rebounds higher (using random value) Ball hits 3rd Quarter = rebounds lower (using random value) Ball hits 4th Quarter = rebounds lower (aka Y--) –  Ramses Brown Jan 25 '11 at 7:47
    
I take it from your description you mean vertical quarter, so that a paddle oriented like so: ====== would have the 1st quarter facing upwards, the 4th downwards, and the 2nd and 3rd are essentially inside (except where exposed on the ends)? –  doppelgreener Jan 25 '11 at 8:31

4 Answers 4

If you want to split the paddle into 4 areas and see which one of the four sections it has hit you could do simple comparisons like your if statement above.. if its above or below the mid point in the X or Y position you will now if its left or right, top or bottom...

Assuming ball.Y and Paddle.Y are in the same coordinate system (I am assuming 0,0 is in the bottom left corner of the screen) and you already know that the two have collided, then

if ( ball.Y > Paddle.Y + (Paddle.Width * 0.5))
{
    Top of Paddle
}
else
{
    Bottom of Paddle
}

And you could extend this to the X coords for Left and right as well.

Hope this helps

share|improve this answer
    
So based on your example, 0.25 would be 1/4th? –  Ramses Brown Jan 25 '11 at 2:31
    
@Slateboard, Yup. Multiplication of decimal forms of fractions is faster than division in most cases :) Bit shifting can also half values (Num >> 1) very fast. I was unsure what data type .Y and .Width would be so I went with the straight math :) –  James Jan 25 '11 at 17:16

To split a paddle into four sections along its Y-axis, you could measure penetration percentage through the bat. Hitting the top would be 0.0f, the bottom would be 1.0f. The second quarter would be between 0.25f and 0.5f, etc.

Following is a method to calculate the penetration depth and a method which translates that into the far more important quarter.

// Note: This method can return a value > 1.0 or < 0.0 if the paddle and ball are
// not actually colliding.
float PenetrationDepth(Vector2 ballOrigin, Vector2 paddleOrigin, float paddleThickness)
{
    float paddleEdge = paddleOrigin.Y - paddleThickness * 0.5f;
    float ballRelativePos = ballOrigin.Y - paddleEdge;

    float ballDepth = ballRelativePos / paddleThickness;
    return ballDepth;
}

enum PenetrationQuarter { None = 0, First, Second, Third, Fourth }

PenetrationQuarter GetPenetrationQuarter(Vector2 ballOrigin, Vector2 paddleOrigin,
    float paddleThickness)
{
    float depth = PenetrationDepth(ballOrigin, paddleOrigin, paddleThickness);
    if (depth > 1.0f || depth < 0.0f) return PenetrationQuarter.None;

    int quarter = (int)(depth * 4) + 1;
    // Edge case: If depth was 1.0, quarter will be 5, which is within quarter 4
    if (quarter == 5) quarter = 4;

    return (PenetrationQuarter)quarter;
}

Edit: Fixed some (fairly terrible) logic errors.

share|improve this answer

The most efficient way I've found to do this exact thing in my game is by inserting this code:

    public void BatHit(int block)
    {
        if (direction > Math.PI * 1.5f || direction < Math.PI * 0.5f)
        {
            switch (block)
            {
                case 1:
                    direction = MathHelper.ToRadians(200);
                    break;
                case 2:
                    direction = MathHelper.ToRadians(195);
                    break;
                case 3:
                    direction = MathHelper.ToRadians(180);
                    break;
                case 4:
                    direction = MathHelper.ToRadians(180);
                    break;
                case 5:
                    direction = MathHelper.ToRadians(165);
                    break;
                case 6:
                    direction = MathHelper.ToRadians(130);
                    break;
            }
        }
        else
        {
            switch (block)
            {
                case 1:
                    direction = MathHelper.ToRadians(310);
                    break;
                case 2:
                    direction = MathHelper.ToRadians(345);
                    break;
                case 3:
                    direction = MathHelper.ToRadians(0);
                    break;
                case 4:
                    direction = MathHelper.ToRadians(0);
                    break;
                case 5:
                    direction = MathHelper.ToRadians(15);
                    break;
                case 6:
                    direction = MathHelper.ToRadians(50);
                    break;
            }
        }

        if (rand.Next(2) == 0)
        {
            direction += MathHelper.ToRadians(rand.Next(3));
        }
            else
        {
            direction -= MathHelper.ToRadians(rand.Next(3));
        }
        AudioManager.Instance.PlaySoundEffect("hit");

    }
share|improve this answer

Johnathan Hobbs is close in his answer. I would suggest ditching corners, and going with a percentage base.

Hitting the paddle on the left-most edge gives an angle of, say, -60 degrees (2pi/3, I think). Hitting the right-most edge is +60 degrees.

So your range is 120 degrees. Calculate the relative Y of where the ball hit, map it from [0 .. 1] (a percentage) to [-60 ... 60] and that's the angle of reflection.

I used something quite similar in my Flash block-paddle game. The benefit of this approach is:

  • simplistic (easy to code)
  • "realistic" (users can understand how it works quickly and "aim" where they want the ball to go).
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.