html5碰撞小球模拟
这里根据动量守恒和能量守恒定理来计算小球的位置,从而模拟完全弹性碰撞下的小球运行轨迹。
html代码:
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 5 <script class="jquery library" src="/js/sandbox/jquery/jquery-1.8.2.min.js" type="text/javascript"></script> 6 <title>碰撞小球</title> 7 </head> 8 <body> 9 <canvas id='box' width="300" height="300" style="border:2px; background:black;"> 10 </canvas> 11 </body> 12 </html>
js代码:
1 //get a random color to render the ball 2 function getRandomColor(){ 3 return (function(m,s,c){ 4 return (c ? arguments.callee(m,s,c-1) : '#') + 5 s[m.floor(m.random() * 16)] 6 })(Math,'0123456789abcdef',5) 7 } 8 9 //get a random number between min and max 10 function getRandomNumber(min, max) { 11 return min + Math.ceil(Math.random() * (max - min)); 12 } 13 14 var balls = []; 15 var ballCount = 4; 16 var boxLen = 300; 17 18 function createBall() { 19 var r = getRandomNumber(10,20); 20 var ball = { 21 m:r, 22 r:r, 23 x:getRandomNumber(0,boxLen-2*r), 24 y:getRandomNumber(0,boxLen-2*r), 25 vx:getRandomNumber(1,3), 26 vy:getRandomNumber(1,3), 27 color:getRandomColor() 28 }; 29 return ball; 30 } 31 32 //test collision 33 function checkCollision(b1, b2) { 34 var dx = b1.x - b2.x; 35 var dy = b1.y - b2.y; 36 var dist = Math.ceil(Math.sqrt(dx * dx + dy * dy)); 37 return dist < b1.r + b2.r; 38 } 39 40 //initialize the balls 41 for(var i = 0; i < ballCount; i++) { 42 var collision = false; 43 while(true) { 44 var b = createBall(); 45 for(var j = 0; j < i; j++) { 46 collision = checkCollision(b,balls[j]); 47 if(collision) break; 48 } 49 if(!collision) { 50 balls[i] = b; 51 break; 52 } 53 } 54 } 55 56 function calcV(m1, m2, v1, v2) { 57 return ((m1 - m2) * v1 + 2 * m2 * v2) / (m1 + m2); 58 } 59 60 function draw() { 61 //handle collisions 62 for(var i = 0; i < balls.length; i++) { 63 for(var j = i + 1; j < balls.length; j++) { 64 if(checkCollision(balls[i],balls[j])) { 65 var b1 = balls[i], b2 = balls[j]; 66 var v1 = { x : b1.vx, y : b1.vy }; 67 var v2 = { x : b2.vx, y : b2.vy }; 68 b1.vx = calcV(b1.m, b2.m, v1.x, v2.x); 69 b1.vy = calcV(b1.m, b2.m, v1.y, v2.y); 70 b2.vx = calcV(b2.m, b1.m, v2.x, v1.x); 71 b2.vy = calcV(b2.m, b1.m, v2.y, v1.y); 72 } 73 } 74 } 75 76 //move the balls 77 for(var i in balls) { 78 var b = balls[i]; 79 b.x += b.vx; 80 b.y += b.vy; 81 var closeSide = false; 82 var maxPos = boxLen - 2 * b.r; 83 if(b.x < 0) { 84 b.x = 0; 85 closeSide = true; 86 } else if(b.x > maxPos) { 87 b.x = maxPos; 88 closeSide = true; 89 } 90 if(closeSide) 91 b.vx = -1 * b.vx; 92 closeSide = false; 93 if(b.y < 0) { 94 b.y = 0; 95 closeSide = true; 96 } else if(b.y > maxPos) { 97 b.y = maxPos; 98 closeSide = true; 99 } 100 if(closeSide) 101 b.vy = -1 * b.vy; 102 } 103 104 //draw the balls 105 var canvas = document.getElementById('box'); 106 var ctx = canvas.getContext('2d'); 107 ctx.fillStyle = "#000"; 108 ctx.fillRect(0,0,canvas.width, canvas.height); 109 for(var i in balls) { 110 var b = balls[i]; 111 ctx.beginPath(); 112 ctx.arc(b.x+b.r, b.y+b.r, b.r, 0, 2 * Math.PI,true); 113 ctx.closePath(); 114 ctx.fillStyle = b.color; 115 ctx.fill(); 116 } 117 setTimeout(draw,10); 118 } 119 120 draw();