ด้วยความช่วยเหลือของชุมชน Stack Overflow ฉันได้เขียนแบบจำลองทางฟิสิกส์พื้นฐาน แต่สนุก
คุณคลิกและลากเมาส์เพื่อเปิดลูกบอล มันจะเด้งไปรอบ ๆ และในที่สุดก็หยุดที่ "พื้น"
คุณสมบัติที่ยิ่งใหญ่ต่อไปของฉันที่ฉันต้องการเพิ่มคือการชนลูกบอล การเคลื่อนที่ของลูกบอลแตกออกเป็นขวานและเวกเตอร์ความเร็ว y ฉันมีแรงโน้มถ่วง (การลดลงของเวกเตอร์ y ในแต่ละขั้นตอน) ฉันมีแรงเสียดทาน (การลดลงเล็กน้อยของเวกเตอร์ทั้งสองแต่ละการชนกับผนัง) ลูกบอลเคลื่อนที่ไปรอบ ๆ อย่างสมจริงอย่างน่าประหลาด
ฉันเดาคำถามของฉันมีสองส่วน:
- วิธีที่ดีที่สุดในการตรวจจับการชนกันของลูกบอลคืออะไร?
ฉันแค่มีวง O (n ^ 2) ที่วนซ้ำลูกบอลแต่ละลูกแล้วตรวจสอบลูกบอลอื่น ๆ เพื่อดูว่ารัศมีนั้นทับกันหรือไม่? - ฉันใช้สมการอะไรในการจัดการลูกบอลเพื่อชนลูก? ฟิสิกส์ 101
มันส่งผลต่อความเร็วของลูกบอลสองลูกที่ x / y เวกเตอร์อย่างไร ทิศทางของผลลัพธ์ที่ลูกบอลสองลูกมุ่งหน้าไปคืออะไร? ฉันจะใช้สิ่งนี้กับลูกบอลแต่ละลูกได้อย่างไร
การจัดการการตรวจจับการชนของ "กำแพง" และการเปลี่ยนแปลงเวกเตอร์ที่เกิดขึ้นนั้นเป็นเรื่องง่าย แต่ฉันเห็นภาวะแทรกซ้อนมากขึ้นจากการชนกันของลูกกลม ด้วยกำแพงฉันต้องเอาค่าลบของเวกเตอร์ x หรือ y ที่เหมาะสมแล้วมันจะไปในทิศทางที่ถูกต้อง กับลูกฉันไม่คิดว่ามันเป็นอย่างนั้น
คำอธิบายอย่างรวดเร็ว: เพื่อความเรียบง่ายฉันตกลงกับการปะทะที่ยืดหยุ่นอย่างสมบูรณ์สำหรับตอนนี้ลูกบอลของฉันทั้งหมดมีมวลเท่ากันในขณะนี้ แต่ฉันอาจเปลี่ยนแปลงสิ่งนั้นในอนาคต
แก้ไข: แหล่งข้อมูลที่ฉันพบว่ามีประโยชน์
ฟิสิกส์ลูกบอล 2 มิติพร้อมเวกเตอร์: การชนสองมิติโดยไม่มีตรีโกณมิติ.
pdf ตัวอย่างการตรวจสอบการชนของลูกบอล 2d: การเพิ่มการตรวจจับการชน
ที่ประสบความสำเร็จ!
ฉันมีระบบตรวจจับการชนของลูกและการตอบสนองที่ยอดเยี่ยม!
รหัสที่เกี่ยวข้อง:
การตรวจจับการชนกัน:
for (int i = 0; i < ballCount; i++)
{
for (int j = i + 1; j < ballCount; j++)
{
if (balls[i].colliding(balls[j]))
{
balls[i].resolveCollision(balls[j]);
}
}
}
วิธีนี้จะตรวจสอบการชนกันของลูกบอลทุกลูก แต่ข้ามการตรวจสอบซ้ำซ้อน (ถ้าคุณต้องตรวจสอบว่าบอล 1 ชนกับบอล 2 หรือไม่แล้วคุณไม่จำเป็นต้องตรวจสอบว่าบอล 2 ชนกับบอล 1 หรือไม่ )
จากนั้นในคลาสบอลของฉันฉันมีวิธีการชนกันของฉัน () และ resolCollision ():
public boolean colliding(Ball ball)
{
float xd = position.getX() - ball.position.getX();
float yd = position.getY() - ball.position.getY();
float sumRadius = getRadius() + ball.getRadius();
float sqrRadius = sumRadius * sumRadius;
float distSqr = (xd * xd) + (yd * yd);
if (distSqr <= sqrRadius)
{
return true;
}
return false;
}
public void resolveCollision(Ball ball)
{
// get the mtd
Vector2d delta = (position.subtract(ball.position));
float d = delta.getLength();
// minimum translation distance to push balls apart after intersecting
Vector2d mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / ball.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2)));
// impact speed
Vector2d v = (this.velocity.subtract(ball.velocity));
float vn = v.dot(mtd.normalize());
// sphere intersecting but moving away from each other already
if (vn > 0.0f) return;
// collision impulse
float i = (-(1.0f + Constants.restitution) * vn) / (im1 + im2);
Vector2d impulse = mtd.normalize().multiply(i);
// change in momentum
this.velocity = this.velocity.add(impulse.multiply(im1));
ball.velocity = ball.velocity.subtract(impulse.multiply(im2));
}
รหัสที่มา: แหล่งที่มาที่สมบูรณ์สำหรับลูกเพื่อลูก collider
หากใครมีคำแนะนำสำหรับวิธีการปรับปรุงตัวจำลองฟิสิกส์พื้นฐานให้ฉันรู้! สิ่งหนึ่งที่ฉันยังไม่ได้เพิ่มคือโมเมนตัมเชิงมุมดังนั้นลูกบอลจะหมุนได้สมจริง ข้อเสนอแนะอื่น ๆ ? ทิ้งข้อความไว้!
Vector2d impulse = mtd.multiply(i);
ควรเป็น i * เวกเตอร์ mtd ปกติ สิ่งที่ต้องการ:Vector2d impulse = mtd.normalize().multiply(i);