Jonathan,
Tôi sẽ làm như Erick gợi ý, nhưng tôi sẽ cẩn thận để đảm bảo các thành phần tốc độ X và Y được lồng vào nhau, nếu không tốc độ chung của quả bóng sẽ thay đổi đơn giản từ một va chạm với mái chèo, đó là vật lý phi thực tế.
Vì vậy, trước tiên tôi sẽ tính tốc độ tổng thể của quả bóng từ .speedX()
và .speedY()
(sử dụng định lý Pythagore), sau đó tính tốc độ X mới từ vị trí của quả bóng so với mái chèo, sau đó đặt tốc độ Y phụ thuộc vào chức năng của tốc độ X mới và tốc độ tổng thể ban đầu, để bóng chỉ thay đổi hướng (trong vô số góc có thể) nhưng luôn duy trì cùng tốc độ chung.
Nói một cách cụ thể hơn, tôi sẽ làm như thế nà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);
}
Lưu ý: Khi thời gian trôi qua, lỗi làm tròn sẽ khiến tốc độ chung trôi chậm so với giá trị ban đầu. Tốc độ tổng thể mong muốn có thể là thứ bạn muốn thêm dưới dạng dữ liệu thành viên m_ball
(thay vì tính toán mỗi lần ở đây) hoặc có thể là thứ bạn muốn cho phép tăng tốc và làm chậm theo các yếu tố chơi trò chơi khác.