我在试图检测两个球之间碰撞时遇到此问题,当一个(或两个)球具有非常高的速度时。我想这是一个非常普遍的问题,我明白为什么会发生。我的猜测是,解决方案将与衍生品有关,我已经设计了一些东西,但如果存在已知的解决方案,我不想“重新发明轮子”。当速度过高时,碰撞检测失败
任何可能引起我的路径的东西都会被赞成!
我做了这个非常简单的例子。如果两个球的速度都是1.5或3,他们会碰撞。如果我们使用更高的东西,比如 50,它会失败。
<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>
我把这个code添加到JSBin。