Skip to content

Injected Globals ​

Open the editor to use these globals live.

Your entry file runs inside a function. These parameters are in scope automatically — do not declare them.

Module files do not receive these globals. Pass dt, state, w, and h as function arguments from the entry file. See Multi-File Imports. (assets and ai are the exceptions — both are available in module files too.)

Quick Reference ​

GlobalTypeDescription
timenumberCumulative simulation time in seconds
dtnumberDelta time since last frame (seconds)
stateobjectMutable object that persists across frames
keysobjectCurrently pressed keys ({ ArrowUp: true, w: true, ... })
wnumberCanvas width in CSS pixels
hnumberCanvas height in CSS pixels
assetsobjectAsset library: images, sprite sheets, and tile grids
aimoduleNot a global — import it (import ai from 'ai'): steering, flocking, and live cursor perception

time ​

javascript
return {
  text: { elapsed: time.toFixed(1) + 's' },
}
PropertyDetail
Typenumber
UnitSeconds
Starts at0
Increases bydt each frame
Resets whenRestart, Reset, or code recompile

time is simulation time, not wall clock. While paused, it does not advance.

dt ​

javascript
state.x += state.vx * dt;
PropertyDetail
Typenumber
UnitSeconds
Typical value~0.016 (60 FPS)
Maximum0.05 (20 FPS floor)

dt is clamped to 50ms so a tab regain does not explode the simulation.

MATH

Euler step: position += velocity * dt. Always multiply forces and velocities by dt so motion stays frame-rate independent.

WARNING

Never assume dt is constant. It fluctuates with load. Fixed increments like state.x += 2 make speed depend on FPS.

state ​

javascript
if (!state.init) {
  state.x = 100;
  state.vx = 0;
  state.init = true;
}

state.vx += 50 * dt;
state.x += state.vx * dt;
PropertyDetail
TypeRecord<string, any>
Initial value{} (plus click fields when present)
PersistsAcross frames until cleared
Cleared byRestart, Reset, page reload, or recompile after edit

Store positions, velocities, arrays, flags — anything. The engine does not read your custom keys except the click fields below.

Pre-injected Properties ​

On canvas click the host writes:

PropertyTypeDescription
state.clickXnumberCanvas-local X of the click
state.clickYnumberCanvas-local Y of the click

Consume them by setting both to undefined after handling. See Mouse & Click Tracking.

keys ​

javascript
if (keys.ArrowUp || keys.w) {
  state.y -= 100 * dt;
}
PropertyDetail
TypeRecord<string, boolean>
Initial value{}
UpdatedEvery keydown / keyup on window
Cleared whenWindow loses focus (blur)

keys is an object whose properties are set to true while a key is held and false when released. Key names follow event.key — use ArrowUp, ArrowDown, ArrowLeft, ArrowRight for arrows, single characters for letter keys (w, a, s, d, r), and for space.

GAME BUILDING

With keys you can build any game — platformers, shooters, puzzles, Snake, Pong, Breakout, and more. Combine with state for game state, dt for frame-rate-independent physics, and mouse clicks for additional input.

w and h ​

javascript
const cx = w / 2;
const cy = h / 2;

return {
  particles: [
    { x: cx, y: cy, r: 20, color: '#8B5CF6' },
  ],
};
PropertyTypeDescription
wnumberCanvas width in CSS pixels
hnumberCanvas height in CSS pixels

These change when the window or editor panel is resized. Prefer w / h over hardcoded positions.

TIP

Center: const cx = w / 2, cy = h / 2. Bottom: h. Right: w.

assets ​

The built-in asset library. Pick assets from the Assets tab in the editor's left panel — clicking one inserts a sprite snippet into your code.

javascript
return {
  sprites: [
    { asset: 'ship-0', x: w / 2, y: h / 2 },
  ],
}
MethodReturnsDescription
assets.image(id)Image | nullLoaded Image for an asset id
assets.size(id){ w, h } | nullNatural pixel size
assets.isLoaded(id)booleanWhether the image is ready
assets.frame(id, index, cols){ sx, sy, sw, sh } | nullSource crop for one frame of a sprite sheet
assets.tiles(id, opts)Sprite[]Lays out a grid of sprites (see below)
assets.tilemap(id, map, opts)Sprite[]Renders a 2D tile map from a sheet (see below)
assets.list()AssetListItem[]All assets: { id, src, category, w, h }

assets.frame ​

Crops one frame out of a sprite sheet. cols is how many columns the sheet has; frames are square cells read left-to-right, top-to-bottom.

javascript
sprites: [
  { asset: 'sheet-tiles', x: 50, y: 50, w: 32, h: 32, src: assets.frame('sheet-tiles', 0, 12) },
]

null when the frame is out of range — pass it to src and the sprite is skipped.

assets.tiles ​

Returns an array of sprites forming a centered grid — perfect for tile maps, floors, and platforms.

javascript
sprites: [
  ...assets.tiles('sheet-tiles', { cols: 6, rows: 3, size: 32, x: w / 2, y: h / 2 }),
]
OptionTypeDefaultDescription
colsnumber—Columns in the grid
rowsnumber—Rows in the grid
sizenumbernatural widthDisplay size of each tile
xnumber0Grid center X
ynumber0Grid center Y

For a plain tile texture (not a sheet) assets.tiles repeats that single image across the grid; for a sheet it steps through frames automatically.

assets.tilemap ​

Renders a 2D tile map from a sprite sheet. Each cell is a sprite positioned on a centered grid; 0 and null cells are skipped (empty space).

javascript
const MAP = [
  [1, 1, 1, 1, 1, 1, 1, 1],
  [1, 0, 0, 0, 0, 0, 0, 1],
  [1, 0, 2, 0, 0, 0, 0, 1],
  [1, 1, 1, 1, 1, 1, 1, 1],
]
sprites: [
  ...assets.tilemap('sheet-tiles', MAP, { tileSize: 32, x: w / 2, y: h / 2 }),
]
OptionTypeDefaultDescription
tileSizenumbernatural cell widthDisplay size of each tile
xnumber0Grid center X
ynumber0Grid center Y

Map cells are number | string | null: a number indexes a frame of the sheet (see assets.frame), a string is a single-image asset id, and null (or 0) leaves the cell empty. The Level editor in the games editor writes maps like this to level.js for you — pick a sheet, paint, drop items, and export.

An exported level.js also exposes the map as game data, so your code can read the exact grid the editor shows (collision, spawn points, collectibles):

ExportDescription
tileMapThe cell grid as an array of rows (frame numbers; 0/null are empty)
tileSizeThe cell size in pixels used for rendering and collision
tileItemsCollectibles placed in the editor, as { asset, x, y, w, h } (absolute centers)

buildLevel returns only the tile sprites — collectibles are not baked in, so your game code can remove them when collected (see the Tile Dash starter in the games picker).

Categories ​

Assets ship in five categories: characters, items, tiles, effects, and backgrounds. The curated library ships with Eyedially — everything is freely usable (Kenney CC0 art + generated pixel art).

GAME BUILDING

assets + sprites + keys + state is everything you need to build platformers, shooters, and collect-them-all games. See the Sprite cookbook.

ai ​

Behavioral AI for simulations that perceive, decide, and act. Unlike the globals above, ai is a built-in module — it is not injected as a global. Import it in any project (the editor, the public /p/:id page, and embeds all ship the same module), then use ai.* to give particles intelligence: react to the live cursor, flock with neighbors, and steer around obstacles.

javascript
import ai from 'ai';
import { seek, flock } from 'ai';

Using ai without an import throws "ai is not defined" — add the import to every file that uses it.

The full tutorial with demos is in the AI cookbook. Quick start — a particle that chases your cursor:

javascript
import ai from 'ai';

if (!state.p) {
  state.p = ai.agent({
    x: 100, y: 100,
    maxSpeed: 180, maxForce: 90,
    brain: (me, sense) => ai.seek(me, sense.mouse.x, sense.mouse.y, 90),
  });
}
ai.think(state.p, ai.sense(state.p, w, h, time), dt);
ai.wrap(state.p, w, h);
HelperDescription
ai.agent({ x, y, vx, vy, maxSpeed, maxForce, brain })Create an agent with an optional brain(agent, sense) => { fx, fy }
ai.think(agent, sense, dt)Run the brain, apply force, clamp speed, move
ai.mouse()Live cursor { x, y, active } over the canvas
ai.sense(agent, w, h, time)Global perception { mouse, bounds, time, w, h }
ai.neighbors(agents, agent, radius)Agents within radius (excludes self)
ai.seek / flee / arrive / pursue / evade / wanderSteering forces
ai.separate / align / cohesion / flockFlocking rules
ai.avoid(agent, obstacles, opts)Obstacle avoidance ({ x, y, r } circles)
ai.limitSpeed / wrap / keepInBoundsMotion helpers

ai.mouse() is the only way to read the live pointer position — clicks are still available as state.clickX/state.clickY.

How Injection Works ​

javascript
new Function('time', 'dt', 'state', 'w', 'h', 'keys', 'assets', '__modules',
  `"use strict"; return (() => { YOUR_CODE })()`
)

Your code runs in an IIFE in strict mode. __modules is the internal import registry — use named import syntax, not __modules directly.

Consequences:

  • Top-level let / const / var reset every frame
  • Only state.* persists between frames
  • Helper functions defined in the entry file are recreated each frame (fine at 60 FPS)