Adding Friction to reduce velocity
<!DOCTYPE html> <html> <head> <style type="text/css"> #myCanvas {/*from w ww . jav a2 s .c o m*/ background: #001022; } #myButtons { bottom: 20px; left: 20px; position: absolute; } #myButtons button { padding: 5px; } </style> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script type="text/javascript"> class Ball{ constructor(x, y, radius, mass, vX, vY, aX, aY) { this.x = x; this.y = y; this.radius = radius; this.mass = mass; this.vX = vX; this.vY = vY; this.aX = aX; this.aY = aY; } } $(document).ready(function() { let canvas = $("#myCanvas"); let context = canvas.get(0).getContext("2d"); let canvasWidth = canvas.width(); let canvasHeight = canvas.height(); $(window).resize(resizeCanvas); function resizeCanvas() { canvas.attr("width", $(window).get(0).innerWidth); canvas.attr("height", $(window).get(0).innerHeight); canvasWidth = canvas.width(); canvasHeight = canvas.height(); }; resizeCanvas(); let playAnimation = true; let startButton = $("#startAnimation"); let stopButton = $("#stopAnimation"); startButton.hide(); startButton.click(function() { $(this).hide(); stopButton.show(); playAnimation = true; animate(); }); stopButton.click(function() { $(this).hide(); startButton.show(); playAnimation = false; }); let balls = new Array(); for (let i = 0; i < 10; i++) { let x = 20+(Math.random()*(canvasWidth-40)); let y = 20+(Math.random()*(canvasHeight-40)); let radius = 5+Math.random()*10; let mass = radius/2; let vX = Math.random()*4-2; let vY = Math.random()*4-2; let aX = 0; let aY = 0; balls.push(new Ball(x, y, radius, mass, vX, vY, aX, aY)); }; // Animation loop that does all the fun stuff function animate() { // Clear context.clearRect(0, 0, canvasWidth, canvasHeight); context.fillStyle = "rgb(255, 255, 255)"; // Loop through every ball let ballsLength = balls.length; for (let i = 0; i < ballsLength; i++) { let tmpBall = balls[i]; for (let j = i+1; j < ballsLength; j++) { let tmpBallB = balls[j]; let dX = tmpBallB.x - tmpBall.x; let dY = tmpBallB.y - tmpBall.y; let distance = Math.sqrt((dX*dX)+(dY*dY)); if (distance < tmpBall.radius + tmpBallB.radius) { let angle = Math.atan2(dY, dX); let sine = Math.sin(angle); let cosine = Math.cos(angle); // Rotate ball position let x = 0; let y = 0; // Rotate ballB position let xB = dX * cosine + dY * sine; let yB = dY * cosine - dX * sine; // Rotate ball velocity let vX = tmpBall.vX * cosine + tmpBall.vY * sine; let vY = tmpBall.vY * cosine - tmpBall.vX * sine; // Rotate ballB velocity let vXb = tmpBallB.vX * cosine + tmpBallB.vY * sine; let vYb = tmpBallB.vY * cosine - tmpBallB.vX * sine; // Reverse the velocities let vTotal = vX - vXb; vX = ((tmpBall.mass - tmpBallB.mass) * vX + 2 * tmpBallB.mass * vXb) / (tmpBall.mass + tmpBallB.mass); vXb = vTotal + vX; // Move balls apart xB = x + (tmpBall.radius + tmpBallB.radius); // Rotate ball positions back tmpBall.x = tmpBall.x + (x * cosine - y * sine); tmpBall.y = tmpBall.y + (y * cosine + x * sine); tmpBallB.x = tmpBall.x + (xB * cosine - yB * sine); tmpBallB.y = tmpBall.y + (yB * cosine + xB * sine); // Rotate ball velocities back tmpBall.vX = vX * cosine - vY * sine; tmpBall.vY = vY * cosine + vX * sine; tmpBallB.vX = vXb * cosine - vYb * sine; tmpBallB.vY = vYb * cosine + vXb * sine; }; }; tmpBall.x += tmpBall.vX; tmpBall.y += tmpBall.vY; if (Math.abs(tmpBall.vX) < 10) { tmpBall.vX += tmpBall.aX; } if (Math.abs(tmpBall.vY) < 10) { tmpBall.vY += tmpBall.aY; } if (Math.abs(tmpBall.vX) > 0.1) { tmpBall.vX *= 0.9; } else { tmpBall.vX = 0; }; if (Math.abs(tmpBall.vY) > 0.1) { tmpBall.vY *= 0.9; } else { tmpBall.vY = 0; } if (tmpBall.x-tmpBall.radius < 0) { tmpBall.x = tmpBall.radius; tmpBall.vX *= -1; tmpBall.aX *= -1; } else if (tmpBall.x+tmpBall.radius > canvasWidth) { tmpBall.x = canvasWidth-tmpBall.radius; tmpBall.vX *= -1; tmpBall.aX *= -1; }; if (tmpBall.y-tmpBall.radius < 0) { tmpBall.y = tmpBall.radius; tmpBall.vY *= -1; tmpBall.aY *= -1; } else if (tmpBall.y+tmpBall.radius > canvasHeight) { tmpBall.y = canvasHeight-tmpBall.radius; // Move away from the edge tmpBall.vY *= -1; tmpBall.aY *= -1; }; context.beginPath(); context.arc(tmpBall.x, tmpBall.y, tmpBall.radius, 0, Math.PI*2); context.closePath(); context.fill(); }; if (playAnimation) { setTimeout(animate, 40); }; }; animate(); }); </script> </head> <body> <canvas id="myCanvas" width="500" height="500"> <!-- Insert fallback content here --> </canvas> <div id="myButtons"> <button id="startAnimation">Start</button> <button id="stopAnimation">Stop</button> </div> </body> </html>