หมายเหตุ: ทั้งหมดต่อไปนี้จะถือว่าพื้นผิวของลูกไม่มีแรงเสียดทาน (ดังนั้นมันจะไม่เริ่มหมุนหรือเด้งต่างกันเพราะมันเป็น)
ในช่วงเวลาที่ชนลูกบอลจะสัมผัสมุม เมื่อวัตถุที่เป็นของแข็งชนกันแรงจะกระทำตามพื้นผิวที่เรียกว่าปกติคือตั้งฉากกับพื้นผิวที่จุดชน
เนื่องจากเป็นลูกบอลแนวตั้งฉากกับพื้นผิวจึงเข้าหากึ่งกลางของลูก ตกลงเรารู้ทิศทางของแรงแล้วขนาดของมันเป็นเท่าไหร่? สมมติว่าการชนกันแบบยืดหยุ่น (และสี่เหลี่ยมไม่สามารถเคลื่อนที่ได้) ลูกบอลจะต้องกระดอนด้วยความเร็วเดียวกับที่มันกระแทก
อนุญาต (nDx, nDy) เป็นความเร็วหลังจากการชน, (oDx, oDy) ความเร็วก่อนการชนและ (x, y) ตำแหน่งของลูกบอล ณ จุดชน สมมติว่ามุมที่ลูกชนกันอยู่ที่ (0,0)
แสดงข้อมูลเชิงลึกของเราเป็นสูตรเรามี:
(nDx, nDy) = (oDx, oDy) + c * (x, y)
length (nDx, nDy) = length (oDx, oDy)
ซึ่งเทียบเท่ากับ:
nDx = oDx + c * x
nDy = oDy + c * y
nDx^2 + nDy^2 = oDx^2 + oDy^2
เราจะได้สมการสองสมการแรกในสมการสุดท้าย
(oDx + c * x)^2 + (oDy + c * y)^2 = oDx^2 + oDy^2
การขยายโดยใช้ทวินามทวิภาค
(a+b)^2 = a^2 + 2ab + b^2
อัตราผลตอบแทน:
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
สมการกำลังสองนี้c
มีสองวิธี, หนึ่งในนั้นคือ 0 เห็นได้ชัดว่านั่นไม่ใช่ทางออกที่เราสนใจโดยทั่วไปทิศทางของลูกบอลจะเปลี่ยนไปเนื่องจากการชน ในการรับโซลูชันอื่นเราแบ่งทั้งสองด้านด้วย c และรับ:
(2 * oDx * x + 2 * oDy * y) + (x^2 + y^2) * c = 0
นั่นคือ:
c = -(2 * oDx * x + 2 * oDy * y) / (x^2 + y^2)
เพื่อสรุปเรามี:
c = -(2 * oDx * x + 2 * oDy * y) / (x^2 + y^2)
nDx = oDx + c * x
nDy = oDy + c * y
แก้ไข : ในรหัส:
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;
}
ข้อควรพิจารณาในการนำไปปฏิบัติบางประการ: ในขณะที่คุณสามารถประมาณ (x, y) ด้วยตำแหน่งของลูกบอลหลังจากขั้นตอนการจำลองการประมาณนี้จะเปลี่ยนมุมของการโก่งตัวและด้วยเหตุนี้จึงสังเกตได้ชัดเจนมากดังนั้นขั้นตอนการจำลองของคุณ ลูกบอลไม่เคลื่อนที่มากกว่า 1/20 ของ diamater ต่อขั้นตอน) สำหรับวิธีการแก้ปัญหาที่แม่นยำยิ่งขึ้นคุณสามารถคำนวณเวลาที่การชนเกิดขึ้นและแยกขั้นตอนการจำลองในเวลานั้นเช่นทำขั้นตอนบางส่วนจนกระทั่งถึงจุดชนและอีกขั้นตอนที่เหลือสำหรับขั้นตอนที่เหลือ
แก้ไข 2: การคำนวณจุดกระทบ
ให้ r คือรัศมี (x0, y0) ตำแหน่งและ (dx, dy) ความเร็วของลูกบอลที่จุดเริ่มต้นของขั้นตอนการจำลอง เพื่อความง่ายเราจะสมมติว่ามุมที่มีปัญหานั้นอยู่ที่ (0,0)
พวกเรารู้:
(x,y) = (x0, y0) + (dx, dy) * t
พวกเราต้องการ
length(x,y) = r
นั่นคือ
(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
นั่นคือสมการกำลังสองใน t หากเลือกปฏิบัติได้
D = b^2 - 4 * a * c
เป็นลบไม่มีวิธีแก้ปัญหาคือลูกบอลจะไม่ชนกับมุมของสนามในปัจจุบัน มิฉะนั้นโซลูชั่นทั้งสองจะได้รับจาก
t1 = (-b - sqrt(D)) / (2 * a)
t2 = (-b + sqrt(D)) / (2 * a)
t1
เรามีความสนใจในเวลาที่การปะทะกันเริ่มต้นซึ่งเป็นเวลาก่อนหน้านี้
วิธีการของคุณจะกลายเป็น:
// 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;