问题描述
网上找了一段canvas小球碰撞运动的代码,代码很棒,但是有个问题就是当两个小球一开始就是交叉的时候,它们的运动轨迹是一样的,按理说运动轨迹是随机的,不知道为什么会出现一起跑的情况?
相关代码
window.onload = function () {
var canvas = document.getElementById("ball");
var cxt = canvas.getContext("2d");
var r = 20;
var maxNum = 5;
var ballArray = new Array();
var maxX = canvas.width;
var maxY = canvas.height;
for (var n = 0; n < maxNum; n++) {
var x = {
x: getRandomNumber(r, maxX - r),
y: getRandomNumber(r, maxY - r),
r: r,
vX: getRandomNumber(0.5, 1),
vY: getRandomNumber(0.5, 1),
color: getRandomColor(),
}
ballArray.push(x);
}
function getRandomColor() {
return (function (m, s, c) {
return (c ? arguments.callee(m, s, c - 1) : '#') +
s[m.floor(m.random() * 16)]
})(Math, '0123456789abcdef', 5)
}
draw();
function draw() {
cxt.fillStyle = "#000";
cxt.fillRect(0, 0, canvas.width, canvas.height);
for (i in ballArray) {
var x = i;
ballArray[i].x += ballArray[i].vX /2;
ballArray[i].y += ballArray[i].vY/2;
if (ballArray[i].x >= maxX - r) {
ballArray[i].x = maxX - r;
ballArray[i].vX = -ballArray[i].vX;
}
if (ballArray[i].x <= r) {
ballArray[i].x = r;
ballArray[i].vX = -ballArray[i].vX;
}
if (ballArray[i].y >= maxY - r) {
ballArray[i].y = maxY - r;
ballArray[i].vY = -ballArray[i].vY;
}
if (ballArray[i].y <= r) {
ballArray[i].y = r;
ballArray[i].vY = -ballArray[i].vY;
}
for (var j = 0; j < maxNum; j++)
if (j !== x) {
if (Math.round(Math.pow(ballArray[x].x - ballArray[j].x, 2) +
Math.pow(ballArray[x].y - ballArray[j].y, 2)) <=
Math.round(Math.pow(r + r, 2))) {
var tempX = ballArray[x].vX;
var tempY = ballArray[x].vY;
ballArray[x].vX = ballArray[j].vX;
ballArray[j].vX = tempX;
ballArray[x].vY = ballArray[j].vY;
ballArray[j].vY = tempY;
}
}
cxt.beginPath();
cxt.fillStyle = ballArray[i].color;
cxt.arc(ballArray[i].x, ballArray[i].y, ballArray[i].r, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
}
setTimeout(function () {
draw();
}, 10);
}
function getRandomNumber(min, max) {
return (min + Math.floor(Math.random() * (max - min + 1)))
}
}
你期待的结果是什么?实际看到的错误信息又是什么?
按理说运动轨迹是随机的,互不影响的。
其中有一个循环,遍历了所有的小球,在循环的开始处,根据小球的速度,来为他进行一段偏移。
根据如下截图,其作用是,在每一个循环里,对这个小球和其他所有小球做一个碰撞校验,如果两个小球发生重叠,则交换这两个小球的速度(可以看出来这个程序实现的不是弹性碰撞,而是简单的交换速度)。
但是呢,这个循环是对所有小球发生的,也就是说,如果两个小球不重叠,那么没关系,其中先遍历到的小球会把两一个小球向相反的方向修改速度,然后下一个小球被循环到的时候,两个小球就会远离,由于速度是一样的,因此会修正到碰撞前的距离,不会第二次触发这个修改。
但是,如果两个小球一开始就有大量重叠,那么第一次修改完以后,遍历到第二个小球时,其速度依然不足以使其离开第一个小球,于是又触发了第二次速度交换。然后他们俩又回到了之前的速度(相当于碰撞检测失效了)
这个同时也解释为什么他们的运动轨迹一样。
上面的说法稍微有点绕,我整理一下。
他们的运动位移是由循环时处理的,其流程是: