const G = 300; // px / s / s
const cvs = document.createElement("canvas");
cvs.width = 300;
cvs.height = 300;
cvs.style.border = "1px solid red";
const ctx = cvs.getContext("2d");
const Ball = (x, y, vx = 0, vy = 0, ax = 0, ay = G, color = "black") => {
const render = () => {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, 10, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
};
const update = (dt) => {
return Ball(
x + dt * vx,
y + dt * vy,
vx + dt * ax,
vy + dt * ay,
ax,
ay,
color
);
}
return { render, update };
}
const randomBalls = n => Array.from(
{ length: n },
() => Ball(
Math.random() * 300,
Math.random() * 300,
-100 + Math.random() * 200,
Math.random() * -200,
0,
G,
`#${[
(Math.floor(Math.random() * 255)).toString(16),
(Math.floor(Math.random() * 255)).toString(16),
(Math.floor(Math.random() * 255)).toString(16)
].join("")}`
)
);
// Game
let balls = randomBalls(100);
let t = null;
let useFrameTime = true;
const frame = dt => {
if (!useFrameTime) dt = 1 / 60;
// Update entities
balls = balls.map(b => b.update(dt));
// Clear window
ctx.clearRect(0, 0, cvs.width, cvs.height);
// Draw new rects
balls.forEach(b => b.render());
}
const loop = ts => {
const dt = t === null ? 0 : ts - t;
t = ts;
frame(dt / 1000);
requestAnimationFrame(loop);
}
document.body.append(cvs);
requestAnimationFrame(loop);
document.querySelector("button").addEventListener("click", () => {
const n = +document.querySelector("input[type=number]").value;
balls = randomBalls(n);
});
document.querySelector("input[type=checkbox]").addEventListener("change", (e) => {
useFrameTime = e.target.checked;
});
body { display: flex; }
<div style="width: 300px">
<p>Increase the count here. Time for all balls to exit the frame should stay roughly the same, but you should see the frame rate drop as you increase the number of entities to render.
</p>
<input type="number" value="100">
<button>Go</button>
<br>
<label><input type="checkbox" checked> Use frame time in render loop</label>
</div>