HTML5
1 Canvas animation
http://www.html5canvastutorials.com/advanced/html5-canvas-animation-stage/
Uniqki code#regex /^/#html / <!-- A simulation model of an elastic collision Author: Huidae Cho Copyright: (C) 2017, 2019, Huidae Cho <https://idea.isnew.info> License: GNU Affero General Public License v3 --> <table style="border:0px;"> <tr><td>ax:</td><td><input id="ax" oninput="ball.x.acc=parseFloat(this.value)*0.1; reanimate()" /></td><td>ay:</td><td><input id="ay" oninput="ball.y.acc=parseFloat(this.value)*0.1; reanimate()" /></td></tr> <tr><td>vx:</td><td><input id="vx" readonly="readonly" /></td><td>vy:</td><td><input id="vy" readonly="readonly" /></td></tr> <tr><td style="text-align:right;">x:</td><td><input id="x" readonly="readonly" /></td><td style="text-align:right;">y:</td><td><input id="y" readonly="readonly" /></td></tr> </table> <canvas id="canvas-bouncing-ball" width="500" height="500"></canvas> <script> var canvas = document.getElementById('canvas-bouncing-ball'); var context = canvas.getContext('2d'); var wall = { mass: 100000 }; var ball = { radius: 0, density: 1, mass: 0, x: { pos: 0, vel: 0, acc: 0.0*9.81, loss: 1, // loss from impact loss2: 0.01, // loss in x from y impact }, y: { pos: 0, vel: 0, acc: 0.1*9.81, loss: 1, // loss from impact loss2: 0.01, // loss in y from x impact } }; var Draw = { rectangle: function (x, y, w, h) { context.beginPath(); context.rect(x, y, w, h); context.fillStyle = '#8ED6FF'; context.fill(); context.lineWidth = 2; context.strokeStyle = 'black'; context.stroke(); }, circle: function(x, y, r) { context.beginPath(); context.arc(x, y, r, 0, 2 * Math.PI, false); context.fillStyle = 'green'; context.fill(); context.lineWidth = 2; context.strokeStyle = '#003300'; context.stroke(); } }; function move(coor1, coor2, min, max) { var vel1 = coor1.vel + coor1.acc; if (coor1.pos + vel1 >= min && coor1.pos + vel1 <= max) { coor1.vel = vel1; coor1.pos += coor1.vel; } else { var wallPos = coor1.pos + vel1 < min ? min : max; var t = (wallPos - coor1.pos) / vel1; // fraction of time before impact vel1 = coor1.vel + coor1.acc * t; // partially accelerated // conservations of momentum and kinetic energy coor1.vel = (ball.mass - wall.mass) / (ball.mass + wall.mass) * vel1; // other losses in coor1 from coor1 impact if (Math.abs(coor1.vel) > coor1.loss) coor1.vel = Math.sign(coor1.vel) * (Math.abs(coor1.vel) - coor1.loss); else coor1.vel = 0; coor1.pos = wallPos + coor1.vel; // other losses in coor2 from coor1 impact if (Math.abs(coor2.vel) > coor2.loss2) coor2.vel = Math.sign(coor2.vel) * (Math.abs(coor2.vel) - coor2.loss2); else coor2.vel = 0; } } function animate() { if (ball.x.vel == 0 && ball.y.vel == 0) { ball.radius = Math.random() * ((canvas.width - 6) * 0.1 - 1) + 10; ball.mass = ball.density * Math.PI * Math.pow(ball.radius, 2); ball.x.pos = Math.random() * (canvas.width - 2 * ball.radius - 4) + ball.radius + 2; ball.y.pos = Math.random() * (canvas.height - 2 * ball.radius - 4) + ball.radius + 2; ball.x.vel = Math.random() * 100 - 50; ball.y.vel = Math.random() * 100 - 50; } move(ball.x, ball.y, ball.radius + 2, canvas.width - ball.radius - 2); move(ball.y, ball.x, ball.radius + 2, canvas.height - ball.radius - 2); context.clearRect(0, 0, canvas.width, canvas.height); Draw.rectangle(1, 1, canvas.width - 2, canvas.height - 2); Draw.circle(ball.x.pos, ball.y.pos, ball.radius); reqID = requestAnimationFrame(animate); document.getElementById('x').value = ball.x.pos.toFixed(3); document.getElementById('y').value = ball.y.pos.toFixed(3); document.getElementById('vx').value = ball.x.vel.toFixed(3); document.getElementById('vy').value = ball.y.vel.toFixed(3); } function reanimate() { cancelAnimationFrame(reqID); ball.x.vel = ball.y.vel = 0; animate(); } var reqID; document.getElementById('ax').value = ball.x.acc.toFixed(3)*10; document.getElementById('ay').value = ball.y.acc.toFixed(3)*10; animate(); </script> #noregex /^/Uniqki output