Skip to content

Commit 5ceafce

Browse files
committed
feat: add littlejs and fix pixijs + threejs
1 parent 7704484 commit 5ceafce

File tree

8 files changed

+183
-137
lines changed

8 files changed

+183
-137
lines changed

bun.lock

Lines changed: 17 additions & 120 deletions
Large diffs are not rendered by default.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"kaplay": "^3001.0.19",
2323
"kontra": "^10.0.2",
2424
"litecanvas": "0.99.0",
25+
"littlejsengine": "^1.11.10",
2526
"melonjs": "^17.4.0",
2627
"phaser": "^3.90.0",
2728
"pixi.js": "^8.12.0",

src/littlejs.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
{{#> head }} LittleJS — JS Game Rendering Benchmark {{/head}}
4+
<body>
5+
<style></style>
6+
{{> header }}
7+
<main>
8+
{{> container }}
9+
<div id="root" class="canvas"></div>
10+
</main>
11+
{{> footer }}
12+
<script type="module" src="/scripts/littlejs.js"></script>
13+
</body>
14+
</html>

src/partials/header.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<a href="./three.html">Three.js</a>
1313
<a href="./pixi.html">Pixi.js</a>
1414
<a href="./litecanvas.html">Litecanvas</a>
15+
<a href="./littlejs.html">LittleJS</a>
1516
<a href="./canvas.html">Canvas</a>
1617
<a href="./dom.html">DOM</a>
1718
</nav>

src/scripts/engine.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ class Engine {
2020
this.fpsContainer = document.querySelector('.fps-container');
2121
this.countLinks = document.querySelectorAll('.count-container a');
2222
this.typeLinks = document.querySelectorAll('.options-container a');
23-
canvas.width = 1024;
24-
canvas.height = 480;
25-
this.width = this.canvas.width;
26-
this.height = this.canvas.height;
23+
this.width = 1024;
24+
this.height = 480;
25+
if (this.canvas) {
26+
this.canvas.width = this.width;
27+
this.canvas.height = this.height;
28+
}
2729
this.count = 0;
2830

2931
this.initCountLink();

src/scripts/littlejs.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import Engine from './engine.js';
2+
import * as little from 'littlejsengine';
3+
4+
class LittleJSEngine extends Engine {
5+
init() {
6+
super.init();
7+
8+
// Clear the canvas
9+
this.rootElement = document.getElementById('root');
10+
11+
// Start the LittleJS engine
12+
if (!this.initialized) {
13+
little.engineInit(
14+
this.gameInit.bind(this),
15+
this.gameUpdate.bind(this),
16+
this.gameUpdatePost.bind(this),
17+
this.gameRender.bind(this),
18+
this.gameRenderPost.bind(this),
19+
this.type === 'sprite' ? ['sprite.png'] : [],
20+
this.rootElement
21+
);
22+
this.initialized = true;
23+
this.rootElement.style.width = this.width + 'px';
24+
this.rootElement.style.height = this.height + 'px';
25+
}
26+
}
27+
28+
gameInit() {
29+
little.setShowWatermark(false);
30+
little.setCanvasFixedSize(little.vec2(this.width, this.height));
31+
little.setCameraScale(1);
32+
little.setCameraPos(little.vec2(this.width / 2, this.height / 2));
33+
little.mainCanvas.style.background = '#1a1a1a';
34+
35+
document
36+
.querySelectorAll('canvas:not(:first-of-type)')
37+
.forEach((canvas) => {
38+
canvas.style.background = 'transparent';
39+
});
40+
41+
// Particle creation
42+
const particles = new Array(this.count);
43+
const rnd = [1, -1];
44+
for (let i = 0; i < this.count; i++) {
45+
const size = 10 + Math.random() * 80;
46+
const x = Math.random() * this.width;
47+
const y = Math.random() * (this.height - size);
48+
const pos = little.vec2(x, y);
49+
const [dx, dy] = [
50+
3 * Math.random() * rnd[Math.floor(Math.random() * 2)],
51+
3 * Math.random() * rnd[Math.floor(Math.random() * 2)],
52+
];
53+
particles[i] = {
54+
pos,
55+
size: size,
56+
dx,
57+
dy,
58+
tile: this.type === 'sprite' ? little.tile(0, 64, 0) : null,
59+
};
60+
}
61+
this.particles = particles;
62+
}
63+
gameUpdate() {
64+
// Particle animation
65+
const particles = this.particles;
66+
for (let i = 0; i < this.count; i++) {
67+
const r = particles[i];
68+
r.pos.x -= r.dx;
69+
r.pos.y -= r.dy;
70+
if (r.pos.x + r.size < 0) r.dx *= -1;
71+
else if (r.pos.y + r.size < 0) r.dy *= -1;
72+
if (r.pos.x > this.width) r.dx *= -1;
73+
else if (r.pos.y > this.height) r.dy *= -1;
74+
}
75+
}
76+
gameUpdatePost() {}
77+
gameRender() {
78+
this.fpsmeter.tick();
79+
for (let i = 0; i < this.particles.length; i++) {
80+
const particle = this.particles[i];
81+
if (this.type === 'sprite') {
82+
little.drawTile(particle.pos, particle.tile.size, particle.tile);
83+
} else {
84+
if (this.type === 'fill') {
85+
little.drawCircle(
86+
particle.pos,
87+
particle.size,
88+
little.WHITE,
89+
1,
90+
little.BLACK
91+
);
92+
}
93+
if (this.type != 'sprite')
94+
little.drawCircle(
95+
particle.pos,
96+
particle.size,
97+
little.rgb(0, 0, 0, 0),
98+
1,
99+
little.WHITE
100+
);
101+
}
102+
}
103+
}
104+
gameRenderPost() {}
105+
106+
render() {
107+
super.render();
108+
}
109+
}
110+
111+
document.addEventListener('DOMContentLoaded', () => {
112+
const engine = new LittleJSEngine();
113+
engine.render();
114+
});

src/scripts/pixi.js

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,23 @@ class PixiEngine extends Engine {
1111

1212
// Setup application and stage
1313
if (this.app) this.app.ticker.destroy();
14-
this.app = new PIXI.Application({
14+
this.app = new PIXI.Application();
15+
await this.app.init({
1516
width: this.width,
1617
height: this.height,
1718
backgroundColor: 0x1a1a1a,
1819
antialias: true,
1920
});
20-
this.app.view.classList.add('canvas');
21+
this.app.canvas.classList.add('canvas');
2122

2223
// Update canvas with application view
2324
const main = document.querySelector('main');
2425
main.removeChild(main.lastElementChild);
25-
main.appendChild(this.app.view);
26+
main.appendChild(this.app.canvas);
2627

2728
// Particle creation
2829
if (this.type === 'sprite') {
29-
this.texture = PIXI.Texture.from('sprite.png');
30+
this.texture = await PIXI.Assets.load('sprite.png');
3031
}
3132
const particles = new Array(this.count);
3233
const rnd = [1, -1];
@@ -44,13 +45,16 @@ class PixiEngine extends Engine {
4445
} else {
4546
particle = new PIXI.Graphics();
4647
if (this.type === 'stroke') {
47-
particle.lineStyle(1, 0xffffff, 1);
48-
particle.drawCircle(-size / 2, -size / 2, size, 0, Math.PI);
48+
particle
49+
.setStrokeStyle({ width: 1, color: 0xffffff })
50+
.circle(-size / 2, -size / 2, size)
51+
.stroke();
4952
} else if (this.type === 'fill') {
50-
particle.beginFill(0xffffff);
51-
particle.lineStyle(1, 0x000000, 1);
52-
particle.drawCircle(-size / 2, -size / 2, size, 0, Math.PI);
53-
particle.endFill();
53+
particle
54+
.setStrokeStyle({ width: 1, color: 0x000000 })
55+
.circle(-size / 2, -size / 2, size)
56+
.fill({ color: 0xffffff })
57+
.stroke();
5458
}
5559
}
5660
particle.position.set(x, y);
@@ -60,7 +64,15 @@ class PixiEngine extends Engine {
6064
this.particles = particles;
6165
}
6266
render() {
63-
this.app.ticker.add(() => {
67+
// Make sure the ticker is initialized
68+
if (!this.app.ticker || !this.particles) {
69+
setTimeout(() => {
70+
this.render();
71+
}, 100);
72+
return;
73+
}
74+
75+
this.app.ticker.add((_time) => {
6476
// Particle animation
6577
const particles = this.particles;
6678
for (let i = 0; i < this.count; i++) {

src/scripts/three.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class ThreeEngine extends Engine {
1818
);
1919
this.camera.position.set(this.width / 2, this.height / 2, 500);
2020
this.renderer = new THREE.WebGLRenderer({
21-
antialias: true,
21+
antialias: false,
2222
depth: false,
2323
precision: 'lowp',
2424
});
@@ -48,7 +48,12 @@ class ThreeEngine extends Engine {
4848
lineMaterial = new THREE.LineBasicMaterial({ color: 0x000000 });
4949

5050
// Sprite texture
51-
const map = new THREE.TextureLoader().load('sprite.png');
51+
const map = new THREE.TextureLoader().load('sprite.png', (texture) => {
52+
texture.colorSpace = THREE.SRGBColorSpace;
53+
texture.minFilter = THREE.NearestFilter;
54+
texture.magFilter = THREE.NearestFilter;
55+
texture.generateMipmaps = false;
56+
});
5257
const material = new THREE.SpriteMaterial({ map: map });
5358

5459
for (let i = 0; i < this.count; i++) {

0 commit comments

Comments
 (0)