Skills

Melonjs Camera And Drawing

Use this skill for camera control and immediate-mode drawing in melonJS, following a...

Install

npx skills add melonjs/melonJS --skill melonjs-camera-and-drawing -g -a claude-code -y
Repository
melonjs/melonJS6.4k
Category
Engineering
Updated
3d ago
License
MIT
Context cost
Mediumabout 3,000 tokens
Runs scripts
No, instructions only

What it does

Use this skill for camera control and immediate-mode drawing in melonJS, following a target, viewport bounds, shake and fade, secondary cameras and what each one draws, and drawing shapes, lines and gradients inside a custom draw(). Covers world versus screen coordinate conversion, clipping and masking, baking with CanvasRenderTarget, and reading pixels back. Triggers on: Camera2d, viewport, follow, offset, look ahead, setBounds, minimap, second camera, split screen, cullMask, visibilityLayer, hide from a camera, shake, fadeIn, fadeOut, worldToLocal, localToWorld, colorMatrix, renderer.fill, renderer.stroke, Rect, Ellipse, Polygon, Line, Gradient, clipRect, mask, CanvasRenderTarget, NoiseTexture2d, lookAt, setBasis, toImageData, getImageData, toBlob, toDataURL, screenshot, read pixels.

Camera and immediate-mode drawing

Following a target

app.viewport.follow(player, app.viewport.AXIS.BOTH, 0.1);

Pass the renderable, not renderable.pos. follow() accepts a Renderable, a Vector2d or a Vector3d and throws invalid target for me.Camera2d.follow for anything else. A renderable's pos is an ObservableVector3d, which is not a Vector3d subclass, so follow(player.pos, …) throws.

The third argument is a damping factor in [0 .. 1], lower is smoother and laggier, 1 snaps. Omit it for a hard lock (it defaults to 1). It is frame-rate independent since 19.7. AXIS.HORIZONTAL / AXIS.VERTICAL / AXIS.BOTH / AXIS.NONE.

Call it from the followed entity's onActivateEvent, using this.parentApp.

To frame the target off centre, set offset; do not follow a helper object. It shifts the view without moving the camera, in world units, and is applied after following and the bounds, so the view can show past them:

app.viewport.follow(player, app.viewport.AXIS.BOTH, 0.1);
app.viewport.offset.set(0, -70);   // look a little above the feet

// or ahead of where the player faces, eased (see math.damp below)
const ahead = facingLeft ? -80 : 80;
app.viewport.offset.x = math.damp(app.viewport.offset.x, ahead, 4, dt / 1000);

Culling, tile layers, parallax ImageLayers, lights and the pointer (localToWorld, worldToLocal) all count it. shake() adds its jitter on top and gives the value back when it ends, so setting it before or during a shake is fine. reset() clears it.

For anything that is NOT the camera, the same smoothing is math.damp. follow() is frame-rate independent for you; a value you smooth yourself is not, and lerp(current, target, alpha) once per frame moves further on a slow frame than on a fast one, so the feel changes with the frame rate:

import { math } from "melonjs";
Read the whole SKILL.md on GitHub

More in Engineering