Announcing Limn Engine
I'm excited to launch Limn Engine — a lightweight, zero-dependency HTML5 Canvas game framework for the browser. No npm install. No build step. No bloated dependency tree. Drop in a single script and start making 2D games.
The Core Idea: Display + Component
Limn Engine is built around two classes that cover 90% of what you need in a 2D game:
Display — The Game Shell
A singleton Display class that manages the canvas, runs the game loop, handles keyboard and mouse input, controls the camera, and manages scenes. Setting up a game is a one-liner:
const display = new Display();
display.start(800, 600);
Let me try creating it step by step.
Component — Every Object in Your Game
A unified Component class that combines position, size, color/image, velocity, physics, and collision detection. No separate "Sprite" and "Body" classes — one object does it all.
const player = new Component(40, 40, "blue", 100, 100);
Components support three modes:
- Rectangle — solid color shapes for rapid prototyping
- Image — loaded from spritesheets or single image files
-
Text — the
Tctxtsubclass for text elements with backgrounds, padding, and alignment
Key Features
Dual-Canvas High-Performance Rendering
Call display.perform() to activate dual-canvas mode. Static backgrounds and tilemaps are drawn once to an offscreen buffer, then composited as a single drawImage() call per frame. This dramatically reduces draw calls and improves frame rates for complex scenes.
display.perform();
display.start(800, 600);
Tilemap Levels
Define game worlds as 2D arrays and initialize the tilemap engine with one call. Supports dynamic tile placement during gameplay — great for destructible environments and breakable blocks.
display.map = [
[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 9, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1]
];
display.tileMap();
Sprite & AnimatedSprite
Load horizontal spritesheets and define named animation clips (idle, run, jump). Animations can loop, ping-pong, or play once — with frame timing and direction flipping built in.
const hero = new AnimatedSprite("hero.png", 64, 64, 400, 300);
hero.addAnimation("idle", 0, 3, 8, true);
hero.addAnimation("run", 4, 7, 12, true);
hero.play("idle");
Physics & Collision Detection
Enable physics on any component with a single property. Built-in collision detection supports both AABB (rectangle) and circular hitboxes.
player.physics = true;
player.gravity = 0.5;
player.bounce = 0.3;
if (player.collide(platforms)) {
player.posY = platform.y - player.height;
player.speedY = 0;
}
Background Effects
Build rich environments with linear and radial gradient backgrounds, solid colors, and a parallax skybox component for atmospheric depth.
display.lgradient("top", "royalblue", "midnightblue");
display.fullscreen();
Audio
Built-in support for background music and sound effects to complete the game experience.
Why Limn?
There are plenty of game frameworks out there. Here's what makes Limn different:
- Zero dependencies — No npm, no webpack, no node_modules. One file, one script tag.
- Small footprint — Tiny enough to read through and understand in a single