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.

I have a simple breakout game I'm working on. The collision code is solid; things bounce as they should and don't pass through things or do other funkiness, but the reflection is a bit simplistic. As a result, it's easy to get into a state where the ball gets stuck in a loop such that the last blocks cannot be hit without dying to break the loop.

Currently, the paddle collision code reflects the Y speed, and mirrors the X speed depending on what side of the paddle it hits:

        // Check for paddle collisions
        if ((m_ball.rect()).intersects(m_paddle.rect())) {
            double ballCenter = m_ball.rect().getX() + (m_ball.rect().getWidth()/2);
            double paddleCenter = m_paddle.rect().getX() + (m_paddle.rect().getWidth()/2);

            m_ball.setSpeedY(m_ball.speedY() * -1);

            if (ballCenter > paddleCenter) {
                m_ball.setSpeedX(Math.abs(m_ball.speedX()));
            } else {
                m_ball.setSpeedX(-Math.abs(m_ball.speedX()));
            }
        }

Is there any way I could make the algorithm more "interesting", and tighten up the control so the ball doesn't keep get stuck bouncing in the same square?

share|improve this question

migrated from stackoverflow.com Dec 1 '11 at 14:46

This question came from our site for professional and enthusiast programmers.

3 Answers 3

up vote 8 down vote accepted

Use a sliding scale to modify the X speed depending on the location on the paddle.

Set some sort of constant for a max X speed change. If the ball hits on the very right side of the paddle, add this constant to the X speed. If it hits on the very left side of the paddle, subtract this constant from the X speed. If it hits in the very middle of the paddle, do not affect the X speed.

Anywhere in between, use a sliding scale to determine the amount to add or subtract to the X speed.

share|improve this answer

Jonathan,

I would do as Erick suggests, but I would be careful to make sure the X and Y speed components remain interlocked, otherwise the ball's overall speed will change simply from a collision with the paddle, which is unrealistic physics.

So I would first compute the ball's overall speed from .speedX() and .speedY() (using the Pythagorean theorem), then compute the new X speed from the position of the ball relative to the paddle, and then set the Y speed dependent on a function of the new X speed and the original overall speed, so that the ball simply changes direction (in an infinite number of possible angles) but always maintains the same overall speed.

To put that more concretely, I would do it like this:

if ((m_ball.rect()).intersects(m_paddle.rect())) {
    double ballWidth = m_ball.rect().getWidth();
    double ballCenterX = m_ball.rect().getX() + ballWidth/2;
    double paddleWidth = m_paddle.rect().getWidth();
    double paddleCenterX = m_paddle.rect().getX() + paddleWidth/2;
    double speedX = m_ball.speedX();
    double speedY = m_ball.speedY();

    // Applying the Pythagorean theorem, calculate the ball's overall
    // speed from its X and Y components.  This will always be a
    // positive value.
    double speedXY = Math.sqrt(speedX*speedX + speedY*speedY);

    // Calculate the position of the ball relative to the center of
    // the paddle, and express this as a number between -1 and +1.
    // (Note: collisions at the ends of the paddle may exceed this
    // range, but that is fine.)
    double posX = (ballCenterX - paddleCenterX) / (paddleWidth/2);

    // Define an empirical value (tweak as needed) for controlling
    // the amount of influence the ball's position against the paddle
    // has on the X speed.  This number must be between 0 and 1.
    final double influenceX = 0.75;

    // Let the new X speed be proportional to the ball position on
    // the paddle.  Also make it relative to the original speed and
    // limit it by the influence factor defined above.
    speedX = speedXY * posX * influenceX;
    m_ball.setSpeedX(speedX);

    // Finally, based on the new X speed, calculate the new Y speed
    // such that the new overall speed is the same as the old.  This
    // is another application of the Pythagorean theorem.  The new
    // Y speed will always be nonzero as long as the X speed is less
    // than the original overall speed.
    speedY = Math.sqrt(speedXY*speedXY - speedX*speedX) *
             (speedY > 0? -1 : 1);
    m_ball.setSpeedY(speedY);
}

Note: As time goes on, rounding errors will cause the overall speed to drift slowly from its original value. The desired overall speed might be something you want to add as member data to m_ball (rather than calculating it each time here), or it might be something you want to allow to speed up and slow down according to other gameplay factors.

share|improve this answer

A lot of break out games will introduce "spin". If the paddle is moving it will influence the X direction of the ball in the direction the paddel is moving.

share|improve this answer

Your Answer

 
discard

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