ジョナサン、
私はエリックが示唆するように行いますが、XとYの速度コンポーネントが連動していることを確認するように注意します。そうしないと、ボールの全体的な速度がパドルとの衝突から単純に変化します。これは非現実的な物理です。
私は最初からボールの全体的な速度を計算しますので、.speedX()
および.speedY()
(ピタゴラスの定理を使用して)、その後、パドルに対するボールの位置から新しいX速度を計算し、新しいX速度の関数に依存してY速度を設定元の全体速度。これにより、ボールは(無限の可能な角度で)方向を変えるだけで、常に同じ全体速度を維持します。
具体的には、次のようにします。
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);
}
注:時間が経過すると、丸め誤差により全体の速度が元の値からゆっくりとドリフトします。望ましい全体的な速度は、m_ball
(ここでは毎回計算するのではなく)メンバーデータとして追加したいものかもしれませんし、他のゲームプレイ要素に従って加速したり減速したりしたいものかもしれません。