Lưu ý: Tất cả các giả định sau đây cho rằng bề mặt của quả bóng là không ma sát (vì vậy nó sẽ không bắt đầu quay hoặc bật lại khác nhau vì nó là).
Tại thời điểm va chạm, bóng sẽ được chạm vào góc. Khi các vật thể rắn va chạm, một lực sẽ tác dụng dọc theo cái gọi là bề mặt bình thường, tức là vuông góc với bề mặt tại điểm va chạm.
Vì nó là một quả bóng, vuông góc với bề mặt là hướng về tâm của quả bóng. Ok, vậy chúng ta biết hướng của lực, còn độ lớn của nó thì sao? Giả sử va chạm đàn hồi (và hình chữ nhật không thể di chuyển), quả bóng phải bật lại với cùng vận tốc mà nó tác động.
Gọi (nDx, nDy) là vận tốc sau va chạm, (oDx, oDy) vận tốc trước khi va chạm và (x, y) vị trí của quả bóng tại điểm va chạm. Chúng ta hãy giả sử thêm góc mà quả bóng va chạm vào là (0,0).
Thể hiện những hiểu biết của chúng tôi như là công thức, chúng tôi có:
(nDx, nDy) = (oDx, oDy) + c * (x, y)
length (nDx, nDy) = length (oDx, oDy)
Điều này tương đương với:
nDx = oDx + c * x
nDy = oDy + c * y
nDx^2 + nDy^2 = oDx^2 + oDy^2
Thay vào hai phương trình đầu tiên trong phương trình cuối cùng, chúng ta nhận được:
(oDx + c * x)^2 + (oDy + c * y)^2 = oDx^2 + oDy^2
Mở rộng bằng cách sử dụng ngực nhị thức
(a+b)^2 = a^2 + 2ab + b^2
sản lượng:
oDx^2 + 2 * oDx * c * x + (c * x) ^ 2 + oDy^2 + 2 * oDy * c * y + (c * y) ^ 2 = oDx^2 + oDy^2
2 * oDx * c * x + 2 * oDy * c * y + (c * x) ^ 2 + (c * y) ^ 2 = 0
(2 * oDx * x + 2 * oDy * y) * c + (x^2 + y^2) * c^2 = 0
Phương trình bậc hai c
này có hai giải pháp, một trong số đó là 0. Rõ ràng, đó không phải là giải pháp mà chúng ta quan tâm, vì nhìn chung hướng của quả bóng sẽ thay đổi do va chạm. Để có được giải pháp khác, chúng tôi chia cả hai bên cho c và nhận:
(2 * oDx * x + 2 * oDy * y) + (x^2 + y^2) * c = 0
Đó là:
c = -(2 * oDx * x + 2 * oDy * y) / (x^2 + y^2)
Để tóm tắt, chúng tôi có:
c = -(2 * oDx * x + 2 * oDy * y) / (x^2 + y^2)
nDx = oDx + c * x
nDy = oDy + c * y
Chỉnh sửa : Trong mã:
if (collision) {
float x = ballX - cornerX;
float y = ballY - cornerY;
float c = -2 * (ballDx * x + ballDy * y) / (x * x + y * y);
ballDx = ballDx + c * x;
ballDy = ballDy + c * y;
}
Một vài cân nhắc khi thực hiện: Mặc dù bạn có thể ước chừng (x, y) với vị trí của quả bóng sau bước mô phỏng, nhưng phép tính gần đúng này sẽ thay đổi góc lệch và do đó rất đáng chú ý, vì vậy các bước mô phỏng của bạn cần phải rất tốt (có lẽ như vậy quả bóng không di chuyển hơn 1/20 diamater của nó mỗi bước). Để có giải pháp chính xác hơn, bạn có thể tính thời gian xảy ra va chạm và tách bước mô phỏng đó tại thời điểm đó, tức là thực hiện một bước cho đến khi va chạm và một bước khác cho phần còn lại của bước.
Chỉnh sửa 2: Tính điểm tác động
Gọi r là bán kính, (x0, y0) vị trí và (dx, dy) vận tốc của quả bóng khi bắt đầu bước mô phỏng. Để đơn giản, hãy giả sử thêm rằng góc trong câu hỏi nằm ở (0,0).
Chúng tôi biết:
(x,y) = (x0, y0) + (dx, dy) * t
Chúng tôi muốn
length(x,y) = r
Đó là
(x0 + dx * t) ^ 2 + (y0 + dy * t) ^ 2 = r^2
x0^2 + 2 * x0 * dx * t + dx^2 * t^2 + y0^2 + 2 * y0 * dy * t + dy^2 * t^2 = r ^ 2
(dx^2 + dy^2) * t^2 + (2 * x0 * dx + 2 * y0 * dy) * t + (x0^2 + y0^2 - r^2) = 0
\____ _____/ \____________ ___________/ \_______ ________/
\/ \/ \/
a b c
Đó là một phương trình bậc hai trong t. Nếu nó phân biệt đối xử
D = b^2 - 4 * a * c
là tiêu cực, nó không có giải pháp, tức là bóng sẽ không bao giờ đánh vào góc trên khóa học hiện tại của nó. Mặt khác, hai giải pháp của nó được đưa ra bởi
t1 = (-b - sqrt(D)) / (2 * a)
t2 = (-b + sqrt(D)) / (2 * a)
Chúng tôi quan tâm đến thời gian vụ va chạm bắt đầu, đó là thời gian sớm hơn t1
.
Phương pháp của bạn sẽ trở thành:
// compute a,b,c and D as given above
if (D >= 0) {
t = (-b - sqrt(D)) / (2 * a);
if (0 < t && t <= ts) {
// collision during this timestep!
x = x + t * dx;
y = y + t * dy;
ts = ts - t;
// change dx and dy using the deflection formula
}
}
x = x + ts * dx;
y = y + ts * dy;