Skip to content

Quick Start

Five minutes, no art. By the end you will have a project, something on screen, and a script that moves it when you press a key — all of it from what ships in the box: the Blank template starts with a camera and nothing else, and a shape draws without needing a texture.

  1. Create the project. In the launcher, click New project, pick the Blank starter, name it, and click Create project. The editor opens assets/scenes/main.esscene — one entity, a Camera.

  2. Put something on screen. In the viewport, open Create… and choose Shape. A white circle appears at the origin and the World Outliner gains an entity carrying a Transform and a ShapeRenderer. Press F2 and rename it Player.

  3. Write the behaviour. Open src/components.ts — the Blank template’s declaration entry — and replace its contents with:

    src/components.ts
    import { defineBehavior, Transform } from 'esengine';
    export const Player = defineBehavior('Player', {
    state: { speed: 300 },
    update(ctx, dt) {
    const x = (ctx.input.isKeyDown('ArrowRight') ? 1 : 0) - (ctx.input.isKeyDown('ArrowLeft') ? 1 : 0);
    const y = (ctx.input.isKeyDown('ArrowUp') ? 1 : 0) - (ctx.input.isKeyDown('ArrowDown') ? 1 : 0);
    if (x === 0 && y === 0) return;
    const t = ctx.get(Transform); // a copy — Transform lives in the engine
    t.position.x += x * ctx.self.speed * dt;
    t.position.y += y * ctx.self.speed * dt;
    ctx.set(Transform, t); // …so hand it back
    },
    });

    Save it. The editor watches your scripts and picks up the new component a moment later.

  4. Attach it. Select Player in the Outliner, then in the Details panel click Add Component and choose Player. A speed field appears, editable like any other — a behaviour’s state is the component’s data.

  5. Play. Press F5 and hold an arrow key. Esc stops, and the scene is exactly as you left it: play runs in its own realm and never writes back to the scene you are editing.

  • One call gave you a component and a system. defineBehavior registers the update hook as a system and returns a component, which is why Player showed up in Add Component without you declaring anything else.
  • state is the component’s data, so the editor can edit it. Change speed in Details and the next run uses your number — code and inspector are two doors to the same field.
  • ctx is the entity’s view of the framectx.self is this entity’s own state, ctx.input is the keyboard, dt is the seconds since the last frame. Multiplying by dt is what makes 300 mean 300 units per second rather than per frame.
  • Scripting — behaviours, systems, where declarations live, and how hot reload picks them up.
  • The Editor — the workspace you just used, in full.
  • ECS Architecture — why a component is data and a system is behaviour.
  • Sprites & Rendering — when you are ready to swap the circle for artwork.