这里根据动量守恒和能量守恒定理来计算小球的位置,从而模拟完全弹性碰撞下的小球运行轨迹。
html代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script class="jquery library" src="/js/sandbox/jquery/jquery-1.8.2.min.js" type="text/javascript"></script>
<title>碰撞小球</title>
</head>
<body>
<canvas id='box' width="300" height="300" style="border:2px; background:black;">
</canvas>
</body>
</html>
js代码:
//get a random color to render the ball
function getRandomColor(){
return (function(m,s,c){
return (c ? arguments.callee(m,s,c-1) : '#') +
s[m.floor(m.random() * 16)]
})(Math,'0123456789abcdef',5)
} //get a random number between min and max
function getRandomNumber(min, max) {
return min + Math.ceil(Math.random() * (max - min));
} var balls = [];
var ballCount = 4;
var boxLen = 300; function createBall() {
var r = getRandomNumber(10,20);
var ball = {
m:r,
r:r,
x:getRandomNumber(0,boxLen-2*r),
y:getRandomNumber(0,boxLen-2*r),
vx:getRandomNumber(1,3),
vy:getRandomNumber(1,3),
color:getRandomColor()
};
return ball;
} //test collision
function checkCollision(b1, b2) {
var dx = b1.x - b2.x;
var dy = b1.y - b2.y;
var dist = Math.ceil(Math.sqrt(dx * dx + dy * dy));
return dist < b1.r + b2.r;
} //initialize the balls
for(var i = 0; i < ballCount; i++) {
var collision = false;
while(true) {
var b = createBall();
for(var j = 0; j < i; j++) {
collision = checkCollision(b,balls[j]);
if(collision) break;
}
if(!collision) {
balls[i] = b;
break;
}
}
} function calcV(m1, m2, v1, v2) {
return ((m1 - m2) * v1 + 2 * m2 * v2) / (m1 + m2);
} function draw() {
//handle collisions
for(var i = 0; i < balls.length; i++) {
for(var j = i + 1; j < balls.length; j++) {
if(checkCollision(balls[i],balls[j])) {
var b1 = balls[i], b2 = balls[j];
var v1 = { x : b1.vx, y : b1.vy };
var v2 = { x : b2.vx, y : b2.vy };
b1.vx = calcV(b1.m, b2.m, v1.x, v2.x);
b1.vy = calcV(b1.m, b2.m, v1.y, v2.y);
b2.vx = calcV(b2.m, b1.m, v2.x, v1.x);
b2.vy = calcV(b2.m, b1.m, v2.y, v1.y);
}
}
} //move the balls
for(var i in balls) {
var b = balls[i];
b.x += b.vx;
b.y += b.vy;
var closeSide = false;
var maxPos = boxLen - 2 * b.r;
if(b.x < 0) {
b.x = 0;
closeSide = true;
} else if(b.x > maxPos) {
b.x = maxPos;
closeSide = true;
}
if(closeSide)
b.vx = -1 * b.vx;
closeSide = false;
if(b.y < 0) {
b.y = 0;
closeSide = true;
} else if(b.y > maxPos) {
b.y = maxPos;
closeSide = true;
}
if(closeSide)
b.vy = -1 * b.vy;
} //draw the balls
var canvas = document.getElementById('box');
var ctx = canvas.getContext('2d');
ctx.fillStyle = "#000";
ctx.fillRect(0,0,canvas.width, canvas.height);
for(var i in balls) {
var b = balls[i];
ctx.beginPath();
ctx.arc(b.x+b.r, b.y+b.r, b.r, 0, 2 * Math.PI,true);
ctx.closePath();
ctx.fillStyle = b.color;
ctx.fill();
}
setTimeout(draw,10);
} draw();