A blazing-fast multithreaded web game engine that handles 20,000+ NPCs without breaking a sweat
npm install @weed.js/engineA blazing-fast multithreaded web game engine that handles 20,000+ NPCs without breaking a sweat.
š Live Demo: https://multithreaded-game-engine.vercel.app/demos
---
Most web game engines choke at a few hundred entities. WeedJS runs 20,000 with room to spare.
Built from the ground up with true parallelism using SharedArrayBuffers and 4 dedicated Web Workers:
- Spatial Worker ā Blazing-fast neighbor queries via spatial hashing
- Logic Workers ā Your game AI runs in parallel across multiple cores
- Physics Worker ā Rock-solid Verlet integration with collision detection
- Renderer Worker ā PixiJS-powered graphics running off the main thread
---
š® Entity Component System ā Clean, composable architecture
ā” O(1) Object Pooling ā Spawn and despawn with zero allocations
š¦
Built-in Flocking AI ā Boids with cohesion, separation, and alignment
š” 2D Lighting & Shadows ā Dynamic lights, shadow casting, muzzle flashes
š Particle System ā Blood splats, sparks, decals that stick to the floor
š· Smart Camera ā Smooth follow, zoom, world bounds clamping
š¬ Animated Sprites ā Spritesheet support with state-based animations
šÆ Collision Callbacks ā Unity-style onCollisionEnter/Stay/Exit
š Scene Management ā Hot-swap between scenes with full cleanup
š Debug UI ā Real-time FPS, entity counts, and visual debugging
---
``javascript
import WEED from "/src/index.js";
const { GameObject, RigidBody, Collider, SpriteRenderer, Scene } = WEED;
// Define your entity
class Zombie extends GameObject {
static components = [RigidBody, Collider, SpriteRenderer];
setup() {
this.rigidBody.maxVel = 3;
this.collider.radius = 15;
}
onSpawned(config) {
this.x = config.x;
this.y = config.y;
this.setSpritesheet("zombie");
this.setAnimation("walk_down");
}
tick(dtRatio) {
// Your AI runs here - neighbors already calculated!
for (let i = 0; i < this.neighborCount; i++) {
const neighborIdx = this.neighbors[i];
const dist = Math.sqrt(this.neighborDistances[i]);
// Do something with nearby entities...
}
}
onCollisionEnter(otherIndex) {
// Bite them!
}
}
// Create scene with 20K zombies
class ZombieScene extends Scene {
static config = {
worldWidth: 5000,
worldHeight: 2000,
spatial: { cellSize: 128, maxNeighbors: 1500 },
physics: { gravity: { x: 0, y: 0 } },
};
static entities = [[Zombie, 20000]];
create() {
for (let i = 0; i < 20000; i++) {
this.spawnEntity("Zombie", {
x: Math.random() * 5000,
y: Math.random() * 2000,
});
}
}
}
// Run it
const game = new WEED.GameEngine({ debug: true });
await game.loadScene(ZombieScene);
`
That's it. 20,000 zombies chasing each other with spatial awareness, physics, and animations. All at 60fps.
---
`javascript
// Blood splatter on collision
ParticleEmitter.emit({
count: { min: 4, max: 8 },
texture: "blood",
x: this.x,
y: this.y,
angleXY: { min: 0, max: 360 },
speed: { min: 0.7, max: 1.5 },
lifespan: 6000,
gravity: 0.15,
stayOnTheFloor: true, // Decal!
});
// Muzzle flash
Flash.create({
x: gun.x,
y: gun.y,
z: 30,
lifespan: 80,
color: 0xffaa00,
intensity: 40000,
});
`
---
`javascript
class TorchLight extends GameObject {
static components = [LightEmitter, ShadowCaster];
setup() {
this.lightEmitter.lightColor = 0xff6600;
this.lightEmitter.lightIntensity = 20000;
this.lightEmitter.height = 100;
this.shadowCaster.shadowRadius = 20;
}
}
`
Entities cast shadows. Lights illuminate. It all just works.
---
`javascript`
tick(dtRatio) {
if (Keyboard.isDown("w")) this.rigidBody.ay -= 0.3;
if (Keyboard.isDown("s")) this.rigidBody.ay += 0.3;
if (Mouse.isDown) {
// Run away from cursor!
}
Camera.follow(this.x, this.y);
}
---
`bash
git clone https://github.com/your-repo/weedjs.git
cd weedjs
node server/node_server.js
> SharedArrayBuffer requires CORS headers. The included server handles this for you.
---
Because it grows fast, spreads everywhere, and just won't die.
Also, this engine is _dope_.
---
ISC
---
Stop counting entities. Start making games. š®