From 49c264370b95eedb1b22044a09247924f80fe10a Mon Sep 17 00:00:00 2001 From: Erik Onarheim Date: Sat, 18 Oct 2025 09:40:36 -0500 Subject: [PATCH] adjust excalibur benchmark to be more accurate This benchmark is concerned with drawing as fast as possible * Toggles engine.physics = false, disables the built in collision subroutines and events * Fixes benchmark code, created new graphics for every actor instead of sharing, this is very graphics memory in-efficient. New instances need to all be uploaded to the GPU. * Uses raw graphics instead of Actors (actors are a lot like GameObjects in other engines and come with a lot of extras not related to drawing) --- package.json | 2 +- src/scripts/excalibur.js | 97 +++++++++++++++++++++------------------- 2 files changed, 53 insertions(+), 46 deletions(-) diff --git a/package.json b/package.json index e8cc6ec..a9e3972 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "babylonjs": "^8.23.1", - "excalibur": "^0.30.3", + "excalibur": "0.31.0", "fpsmeter": "^0.3.1", "hilojs": "^2.0.2", "kaboom": "^2000.2.10", diff --git a/src/scripts/excalibur.js b/src/scripts/excalibur.js index 7617a5c..022b4e7 100644 --- a/src/scripts/excalibur.js +++ b/src/scripts/excalibur.js @@ -2,71 +2,77 @@ import * as ex from 'excalibur'; import Engine from './engine.js'; export class Scene extends ex.Scene { + particles = []; onActivate(ctx) { - const engine = ctx.engine; - this.engine = ctx.data.engine; + this.benchmarkEngine = ctx.data.engine; this.clear(); // Particle creation - const particles = new Array(this.engine.count); + this.particles = new Array(this.benchmarkEngine.count); const rnd = [1, -1]; const spriteImage = new ex.ImageSource('sprite.png'); spriteImage.load(); - for (let i = 0; i < this.engine.count; i++) { + const sprite = ex.Sprite.from(spriteImage); + + const random = new ex.Random(); + let randomCircles = []; + + for (let i = 0; i < 80; i++) { const size = 10 + Math.random() * 80; - const x = Math.random() * this.engine.width; - const y = Math.random() * (this.engine.height - size); - const [dx, dy] = [ - 3 * Math.random() * rnd[Math.floor(Math.random() * 2)], - 3 * Math.random() * rnd[Math.floor(Math.random() * 2)], - ]; + const x = Math.random() * this.benchmarkEngine.width; + const y = Math.random() * (this.benchmarkEngine.height - size); - const particle = new ex.Actor({ + const circle = new ex.Circle({ x: x, y: y, radius: size, + color: + this.benchmarkEngine.type === 'stroke' + ? ex.Color.Transparent + : ex.Color.fromRGB(255, 255, 255), + strokeColor: + this.benchmarkEngine.type === 'stroke' + ? ex.Color.fromRGB(255, 255, 255) + : ex.Color.fromRGB(0, 0, 0), + strokeWidth: this.benchmarkEngine.type === 'stroke' ? 1 : undefined, }); + randomCircles.push(circle); + } + for (let i = 0; i < this.benchmarkEngine.count; i++) { + const size = 10 + Math.random() * 80; + const x = Math.random() * this.benchmarkEngine.width; + const y = Math.random() * (this.benchmarkEngine.height - size); + const [dx, dy] = [ + 3 * Math.random() * rnd[Math.floor(Math.random() * 2)], + 3 * Math.random() * rnd[Math.floor(Math.random() * 2)], + ]; - if (this.engine.type === 'sprite') { - const sprite = ex.Sprite.from(spriteImage); - particle.graphics.use(sprite); + this.particles[i] = { x, y, size: size, dx, dy, graphics: null }; + if (this.benchmarkEngine.type === 'sprite') { + this.particles[i].graphics = sprite; } else { - const circle = new ex.Circle({ - x: x, - y: y, - radius: size, - color: - this.engine.type === 'stroke' - ? ex.Color.Transparent - : ex.Color.fromRGB(255, 255, 255), - strokeColor: - this.engine.type === 'stroke' - ? ex.Color.fromRGB(255, 255, 255) - : ex.Color.fromRGB(0, 0, 0), - strokeWidth: this.engine.type === 'stroke' ? 1 : undefined, - }); - particle.graphics.use(circle); + this.particles[i].graphics = random.pickOne(randomCircles); } - this.add(particle); - - particles[i] = { x, y, size: size, dx, dy, el: particle }; - - particle.on("postupdate", () => { - const r = particles[i]; - r.x -= r.dx; - r.y -= r.dy; - if (r.x + r.size < 0) r.dx *= -1; - else if (r.y + r.size < 0) r.dy *= -1; - if (r.x > engine.screen.drawWidth) r.dx *= -1; - else if (r.y > engine.screen.drawHeight) r.dy *= -1; - r.el.pos.x = r.x; - r.el.pos.y = r.y; - }); } } onPostUpdate() { - this.engine.fpsmeter.tick(); + for (let i = 0; i < this.benchmarkEngine.count; i++) { + const r = this.particles[i]; + r.x -= r.dx; + r.y -= r.dy; + if (r.x + r.size < 0) r.dx *= -1; + else if (r.y + r.size < 0) r.dy *= -1; + if (r.x > this.engine.screen.drawWidth) r.dx *= -1; + else if (r.y > this.engine.screen.drawHeight) r.dy *= -1; + } + this.benchmarkEngine.fpsmeter.tick(); + } + onPostDraw(ctx) { + for (let i = 0; i < this.benchmarkEngine.count; i++) { + const particle = this.particles[i]; + particle.graphics.draw(ctx, particle.x, particle.y); + } } } @@ -89,6 +95,7 @@ class ExcaliburEngine extends Engine { width: this.width, height: this.height, canvasElement: this.canvas, + physics: false, // this benchmark is only doing drawing backgroundColor: ex.Color.fromRGB(26, 26, 26), scenes: { scene: Scene } });