Ich habe dieses Problem beim Versuch, Kollisionen zwischen zwei Kugeln zu erkennen, wenn einer (oder beide) eine sehr hohe Geschwindigkeit haben. Ich denke, das ist ein sehr häufiges Problem und ich verstehe, warum es passiert. Meine Vermutung ist, dass die Lösung mit Derivaten zu tun haben wird, ich habe bereits etwas entworfen, aber ich möchte das Rad nicht neu erfinden, wenn es eine bekannte Lösung gibt.Kollisionserkennung schlägt fehl, wenn Geschwindigkeit zu hoch ist
Alles, was meinen Weg beleuchten kann, wird gelehrt!
Ich habe dieses sehr einfache Beispiel. Wenn beide Bälle eine Geschwindigkeit von sagen wir 1,5 oder 3 haben, kollidieren sie. Wenn wir etwas sehr viel verwenden, wie 50, wird es fehlschlagen.
<html>
<head>
<title>Collision test</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const width = window.innerWidth;
const height = window.innerHeight-4;
const center = { x: width/2, y: height/2 };
canvas.width = width;
canvas.height = height;
// Ball Class Definition
class Ball {
constructor(x, y, mass, direction, speed, color) {
this.x = x;
this.y = y;
this.vx = (Math.cos(direction) * speed) || 0;
this.vy = (Math.sin(direction) * speed) || 0;
this.mass = mass || 1;
this.radius = mass * 3;
this.color = color || "#000000";
}
update() {
this.x += this.vx;
this.y += this.vy;
}
}
let speedA = 1.5;
let speedB = 1;
// Create two balls that will collide
let ballA = new Ball(center.x - 300, center.y, 3, Math.PI*2, speedA, "green");
let ballB = new Ball(center.x + 100, center.y, 2.2, Math.PI, speedB, "green");
// Main update/draw function
function draw() {
window.requestAnimationFrame(draw);
ctx.clearRect(0,0, width, height);
ballA.update();
ballB.update();
handleCollisions(ballA, ballB);
// Draw Ball A
ctx.beginPath();
ctx.arc(ballA.x, ballA.y, ballA.radius, 0, Math.PI * 2, false);
ctx.fillStyle = ballA.color;
ctx.fill();
// Draw Ball B
ctx.beginPath();
ctx.arc(ballB.x, ballB.y, ballB.radius, 0, Math.PI * 2, false);
ctx.fillStyle = ballB.color;
ctx.fill();
}
// Detect and handle collision
function handleCollisions(p1, p2) {
let xDist, yDist;
xDist = p1.x - p2.x;
yDist = p1.y - p2.y;
let distSquared = xDist*xDist + yDist*yDist;
//Check the squared distances instead of the the distances, same result, but avoids a square root.
if(distSquared <= (p1.radius + p2.radius)*(p1.radius + p2.radius)){
let xVelocity = p2.vx - p1.vx;
let yVelocity = p2.vy - p1.vy;
let dotProduct = xDist*xVelocity + yDist*yVelocity;
//Neat vector maths, used for checking if the objects moves towards one another.
if(dotProduct > 0){
let collisionScale = dotProduct/distSquared;
let xCollision = xDist * collisionScale;
let yCollision = yDist * collisionScale;
//The Collision vector is the speed difference projected on the Dist vector,
//thus it is the component of the speed difference needed for the collision.
let combinedMass = p1.mass + p2.mass;
let collisionWeightA = 2 * p2.mass/combinedMass;
let collisionWeightB = 2 * p1.mass/combinedMass;
p1.vx += collisionWeightA * xCollision;
p1.vy += collisionWeightA * yCollision;
p2.vx -= collisionWeightB * xCollision;
p2.vy -= collisionWeightB * yCollision;
}
}
}
draw();
</script>
</body>
</html>
Ich habe diese code zu JSBin hinzugefügt.