检查两个圆之间的距离
Checking Distance Between Two Circles
所以我有这段代码可以创建多个球,它们获得随机的 x、y 和速度,它们只是在屏幕上弹跳,这部分效果很好,但我想要更多。我一直在想办法让它们在相反的方向发生碰撞和反弹。我一直在试图弄清楚我做错了什么,但我已经花了大约 30 分钟才弄清楚,有什么建议吗?
var canvas = document.getElementById('gamecanvas');
var c = canvas.getContext('2d');
var ma = Math.random;
var mo = Math.round;
var ballcount = 5;
var balls = [];
function setup() {
//canvas
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
for (i = 0; i < ballcount; i++) {
//ball setup
r = mo(ma() * 40) + 10;
y = mo(ma() * (canvas.height - r));
x = mo(ma() * (canvas.width - r));
vx = mo(ma() * 20) - 10;
vy = mo(ma() * 20) - 10;
balls[i] = { x, y, vx, vy, r };
}
}
function gameloop() {
//clear
c.clearRect(0, 0, canvas.width, canvas.height);
c.strokeStyle = 'white';
//move
for (i = 0; i < ballcount; i++) {
balls[i].x += balls[i].vx;
balls[i].y += balls[i].vy;
//wall collision
if (balls[i].x <= balls[i].r) {
balls[i].x = balls[i].r;
balls[i].vx *= -1;
}
if (balls[i].y <= balls[i].r) {
balls[i].y = balls[i].r;
balls[i].vy *= -1;
}
if (balls[i].x >= canvas.width - balls[i].r) {
balls[i].x = canvas.width - balls[i].r;
balls[i].vx *= -1;
}
if (balls[i].y >= canvas.height - balls[i].r) {
balls[i].y = canvas.height - balls[i].r;
balls[i].vy *= -1;
}
//ball collision
for (j = 0; j < ballcount; j++) {
if(i != j) {
dx = balls[j].x - balls[i].x;
dy = balls[j].y - balls[i].y;
rs = balls[j].r + balls[i].r;
if(Math.sqrt((dx * dx) - (dy * dy)) < rs) {
balls[i].vx *= -1;
balls[j].vx *= -1;
}
}
}
}
//draw
c.beginPath();
for (i = 0; i < ballcount; i++) {
c.moveTo(balls[i].x + balls[i].r, balls[i].y);
c.arc(balls[i].x, balls[i].y, balls[i].r, 0, 7);
}
c.stroke();
}
setup();
setInterval(gameloop, 1000 / 60);
body {
background-color: black;
overflow: hidden;
margin: 0;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="index.css">
<title>Bslls</title>
</head>
<body id="body">
<canvas id="gamecanvas"></canvas>
<script src="index.js"></script>
</body>
</html>
我过去曾尝试做类似的事情,我遇到了一些用 js 模拟物理的库,其中之一是 http://wellcaffeinated.net/PhysicsJS/。
这是一个简单的图书馆。
提示:
有两个子问题:找到碰撞点和反映轨迹。
要找到碰撞点,可以这样推理:
将一个球膨胀另一个球的半径,让另一个球缩小为一个点;
考虑小球与点的相对速度(即向量差),将小球移至原点
现在你有一个固定的圆和一个沿直线移动的点。您可以通过求解二次方程找到圆和线之间的第一个交点。最方便的是使用点运动的参数方程与圆的隐式方程。同样的价格,你得到会议时间。
为了反映轨迹,考虑交点圆的法线是入射方向和反射方向的平分线。在完美弹性冲击的情况下,反射后的速度与之前相同。
现在通过撤销初始变换,您可以找到两个球的交点和新方向。
一点向量微积分:-)
你必须检查两个球之间的距离是否小于它们的半径之和。
//let b1 be ball-1 and b2 be ball-2
var distance = Math.sqrt((b2.x - b1.x) ** 2 + (b2.y - b1.y) ** 2);
if(b1.r + b2.r <= distance) {
//colliding
}
但是在你的情况下,由于球在一个小space中移动得太快,你无法正确检测到碰撞。
也就是说,您的碰撞检测数学工作正常,问题是您无法在正确的时间检测到碰撞!
你的球会直线运动,所以考虑两个球在直线运动,你必须检查它们在相应运动线的任何部分时是否会碰撞。
将涉及一些更复杂的数学!
所以我有这段代码可以创建多个球,它们获得随机的 x、y 和速度,它们只是在屏幕上弹跳,这部分效果很好,但我想要更多。我一直在想办法让它们在相反的方向发生碰撞和反弹。我一直在试图弄清楚我做错了什么,但我已经花了大约 30 分钟才弄清楚,有什么建议吗?
var canvas = document.getElementById('gamecanvas');
var c = canvas.getContext('2d');
var ma = Math.random;
var mo = Math.round;
var ballcount = 5;
var balls = [];
function setup() {
//canvas
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
for (i = 0; i < ballcount; i++) {
//ball setup
r = mo(ma() * 40) + 10;
y = mo(ma() * (canvas.height - r));
x = mo(ma() * (canvas.width - r));
vx = mo(ma() * 20) - 10;
vy = mo(ma() * 20) - 10;
balls[i] = { x, y, vx, vy, r };
}
}
function gameloop() {
//clear
c.clearRect(0, 0, canvas.width, canvas.height);
c.strokeStyle = 'white';
//move
for (i = 0; i < ballcount; i++) {
balls[i].x += balls[i].vx;
balls[i].y += balls[i].vy;
//wall collision
if (balls[i].x <= balls[i].r) {
balls[i].x = balls[i].r;
balls[i].vx *= -1;
}
if (balls[i].y <= balls[i].r) {
balls[i].y = balls[i].r;
balls[i].vy *= -1;
}
if (balls[i].x >= canvas.width - balls[i].r) {
balls[i].x = canvas.width - balls[i].r;
balls[i].vx *= -1;
}
if (balls[i].y >= canvas.height - balls[i].r) {
balls[i].y = canvas.height - balls[i].r;
balls[i].vy *= -1;
}
//ball collision
for (j = 0; j < ballcount; j++) {
if(i != j) {
dx = balls[j].x - balls[i].x;
dy = balls[j].y - balls[i].y;
rs = balls[j].r + balls[i].r;
if(Math.sqrt((dx * dx) - (dy * dy)) < rs) {
balls[i].vx *= -1;
balls[j].vx *= -1;
}
}
}
}
//draw
c.beginPath();
for (i = 0; i < ballcount; i++) {
c.moveTo(balls[i].x + balls[i].r, balls[i].y);
c.arc(balls[i].x, balls[i].y, balls[i].r, 0, 7);
}
c.stroke();
}
setup();
setInterval(gameloop, 1000 / 60);
body {
background-color: black;
overflow: hidden;
margin: 0;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="index.css">
<title>Bslls</title>
</head>
<body id="body">
<canvas id="gamecanvas"></canvas>
<script src="index.js"></script>
</body>
</html>
我过去曾尝试做类似的事情,我遇到了一些用 js 模拟物理的库,其中之一是 http://wellcaffeinated.net/PhysicsJS/。 这是一个简单的图书馆。
提示:
有两个子问题:找到碰撞点和反映轨迹。
要找到碰撞点,可以这样推理:
将一个球膨胀另一个球的半径,让另一个球缩小为一个点;
考虑小球与点的相对速度(即向量差),将小球移至原点
现在你有一个固定的圆和一个沿直线移动的点。您可以通过求解二次方程找到圆和线之间的第一个交点。最方便的是使用点运动的参数方程与圆的隐式方程。同样的价格,你得到会议时间。
为了反映轨迹,考虑交点圆的法线是入射方向和反射方向的平分线。在完美弹性冲击的情况下,反射后的速度与之前相同。
现在通过撤销初始变换,您可以找到两个球的交点和新方向。
一点向量微积分:-)
你必须检查两个球之间的距离是否小于它们的半径之和。
//let b1 be ball-1 and b2 be ball-2
var distance = Math.sqrt((b2.x - b1.x) ** 2 + (b2.y - b1.y) ** 2);
if(b1.r + b2.r <= distance) {
//colliding
}
但是在你的情况下,由于球在一个小space中移动得太快,你无法正确检测到碰撞。
也就是说,您的碰撞检测数学工作正常,问题是您无法在正确的时间检测到碰撞!
你的球会直线运动,所以考虑两个球在直线运动,你必须检查它们在相应运动线的任何部分时是否会碰撞。
将涉及一些更复杂的数学!