Stress test! Move the mouse or touch the canvas to make rectangles.
Stress test! Move the mouse or touch the canvas to make rectangles.
let darkMode =
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
const gravity = 0.1;
class Ball extends Circle {
constructor(x, y) {
super(10);
this.setPosition(x, y);
this.velocity = {
x: Randomizer.nextFloat(-2, 2),
y: Randomizer.nextFloat(0, 1),
};
this.setColor(Randomizer.nextColor());
add(this);
}
update() {
this.y = Math.min(this.y, getHeight() - this.radius - 1);
this.velocity.y += gravity;
this.x += this.velocity.x;
this.y += this.velocity.y;
if (this.y + this.radius >= getHeight()) {
this.velocity.y = Randomizer.nextFloat(-2, -6);
}
if (this.x - this.radius < 0 || this.x + this.radius > getWidth()) {
this.velocity.x *= -1;
}
}
}
class BouncingBox extends Rectangle {
filled = true;
hasBorder = false;
constructor(x, y) {
super(10, 10);
this.setPosition(x, y);
this.velocity = {
x: Randomizer.nextFloat(-1, 1),
y: Randomizer.nextFloat(0, 1),
};
this.setColor(Randomizer.nextColor());
this.setRotation(Math.random() * 350);
//this.setBorderColor(Randomizer.nextColor());
add(this);
}
update() {
this.y = Math.min(this.y, getHeight() - this.height - 1);
this.velocity.y += gravity;
this.x = this.x + this.velocity.x;
this.y += this.velocity.y;
if (this.y + this.height >= getHeight()) {
this.velocity.y = Randomizer.nextFloat(-2, -8);
}
if (this.x - this.width < 0 || this.x + this.width > getWidth()) {
this.velocity.x *= -1;
}
}
}
mouseMoveMethod(e => {
for (let i = 100; i--; ) {
new BouncingBox(e.getX(), e.getY());
}
});
// library code
const debug = true;
let averageFPS = 0;
const fpsText = new Text(averageFPS);
const elementsLabel = new Text(0);
if (debug) {
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
fpsText.setAnchor({ vertical: 0, horizontal: 1 });
fpsText.setPosition(getWidth(), 0);
fpsText.setColor(darkMode ? 'white' : 'black');
elementsLabel.setAnchor({ vertical: 0, horizontal: 1 });
elementsLabel.setPosition(getWidth(), fpsText.height);
elementsLabel.setColor(darkMode ? 'white' : 'black');
add(fpsText);
add(elementsLabel);
}
__graphics__.shouldUpdate = false;
let frameTimeBufferMS = 0;
let frameTimeLastMS = 0;
const frameRate = 60;
const lerp = (v, min, max) => {
return min + v * (max - min);
};
const update = (frameTimeMS = 0) => {
requestAnimationFrame(update);
let frameTimeDeltaMS = frameTimeMS - frameTimeLastMS;
frameTimeLastMS = frameTimeMS;
frameTimeBufferMS = Math.min(frameTimeBufferMS + frameTimeDeltaMS, 50);
let deltaSmooth = 0;
if (frameTimeBufferMS < 0 && frameTimeBufferMS > -9) {
// force an update each frame if time is close enough (not just a fast refresh rate)
deltaSmooth = frameTimeBufferMS;
frameTimeBufferMS = 0;
}
if (debug) {
averageFPS = lerp(0.05, averageFPS, 1e3 / (frameTimeDeltaMS || 1));
fpsText.setLabel(`fps: ${averageFPS.toFixed(1)}`);
elementsLabel.setLabel(`elements: ${__graphics__.elementPool.length}`);
}
// update multiple frames if necessary in case of slow framerate
for (; frameTimeBufferMS >= 0; frameTimeBufferMS -= 1e3 / frameRate) {
__graphics__.elementPool.forEach(element => {
if (element.alive) {
element.update?.();
}
});
}
frameTimeBufferMS += deltaSmooth;
__graphics__.redraw();
};
update();