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
colsnumberColumns in the grid
rowsnumberRows 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)