A modern, plugin-free HTML5 game engine
npm install melonjsimport { Application, Sprite, loader } from "melonjs";
// create a new melonJS application
const app = new Application(1218, 562, {
parent: "screen",
scale: "auto",
backgroundColor: "#202020",
});
// initialize it (builds the renderer and appends the canvas)
await app.init();
// load and add a sprite
loader.preload([{ name: "player", type: "image", src: "player.png" }], () => {
app.world.addChild(new Sprite(609, 281, { image: "player" }));
});Note: since version 20.0,
await app.init()is required after constructing theApplication. The WebGPU backend, whichAUTOtries first where available, acquires its GPU device asynchronously; the call resolves without suspending on the WebGL and Canvas backends.
| Feature | Description |
|---|---|
| Rendering | WebGPU, WebGL 2 and Canvas 2D with automatic fallback — the same feature set on every backend |
| 3D | Perspective Camera3d, mesh instancing, ground shadows, point and spot lights, glTF/GLB and OBJ/MTL loading |
| Tiled Maps | First-class Tiled map editor support (TMX/JSON), with GPU-accelerated tile rendering for orthogonal maps |
| Sprites | Texture atlas, animation, TexturePacker & Aseprite support |
| Physics | Built-in SAT collision with gravity and friction, shape-level collision events, and a PhysicsAdapter interface for Box2D (planck) or Matter.js |
| Audio | Web Audio API with format fallback, plus procedural tone and noise generation |
| Input | Keyboard, mouse, touch, gamepad |
| Particles | Configurable ParticleEmitter, with a reference space so particles can be measured from the emitter, the world, or any container |
| Effects | All thirteen CSS blend modes on every renderer, tinting, masking, and camera post-processing chains |
| Custom Shaders | Per-sprite ShaderEffect carrying both GLSL and WGSL, so one effect runs on either GPU backend |
| UI | Built-in UI components (buttons, text input, containers) |
Load a level created with the Tiled map editor. melonJS supports orthogonal, isometric, and hexagonal maps with multiple layers, animated tiles, and collision shapes.
import { level } from "melonjs";
// load a level by name (must be preloaded first)
level.load("myLevel");See: level, TMXTileMap
Create a sprite from a texture atlas (e.g. exported from TexturePacker or Aseprite) and define animation sequences from named frames.
import { Sprite, TextureAtlas, loader } from "melonjs";
// create a texture atlas from preloaded JSON + image
const atlas = new TextureAtlas(loader.getJSON("atlas"), loader.getImage("atlas"));
// create a sprite with animation frames from the atlas
const player = new Sprite(100, 100,
atlas.getAnimationSettings(["walk01.png", "walk02.png", "walk03.png"])
);See: Sprite, TextureAtlas
Bind physical keys or gamepad buttons to named actions, then check those actions in your game logic.
import { input } from "melonjs";
// bind the spacebar and gamepad button to a "jump" action
input.bindKey(input.KEY.SPACE, "jump");
// check if the action is active (e.g. in an update loop)
if (input.isKeyPressed("jump")) {
// make the player jump
}See: input
Attach a physics body with a collision shape to any renderable. The engine handles gravity, velocity, friction, and collision detection automatically.
import { Body, Rect, collision } from "melonjs";
// create a rectangular collision body (x, y, width, height)
this.body = new Body(this, new Rect(0, 0, 32, 32));
// set collision type so the engine knows how to handle collisions
this.body.collisionType = collision.types.PLAYER_OBJECT;
// set movement limits and friction
this.body.setMaxVelocity(3, 15);
this.body.setFriction(0.4, 0);Apply a per-sprite fragment shader using ShaderEffect. You only need to write the color transformation — the vertex shader and texture sampling are handled automatically. Runs on both GPU backends — write the body once and it is realized as GLSL or WGSL for the active renderer — and is silently ignored in Canvas mode.
import { ShaderEffect } from "melonjs";
// apply a grayscale effect to a sprite
mySprite.addPostEffect(new ShaderEffect(renderer, `
vec4 apply(vec4 color, vec2 uv) {
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
return vec4(vec3(gray), color.a);
}
`));See: ShaderEffect, addPostEffect
