Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sanchedev/tiny-engine/llms.txt

Use this file to discover all available pages before exploring further.

Scenes are the top-level containers for game content in tiny-engine. Each scene holds a root node tree that the engine starts, updates, and renders every frame. Swapping scenes — for example, transitioning from a main menu to a level — is handled by the SceneManager, which tears down the old node tree and loads the new one cleanly.

Creating a Scene

A Scene is constructed with a single function argument that returns a Node (or a Promise<Node> for async loading). The simplest form passes the root node directly; the lazy-loaded form uses a dynamic import() so the scene’s code is only fetched when it is first needed.
import { Scene } from 'tiny-engine'
import { Node } from 'tiny-engine/nodes'

// Eager — the node is constructed immediately
const menuScene = new Scene(() => new Node({ children: [] }))

// Lazy — the module is fetched only when the scene is first loaded
const gameScene = new Scene(
  async () => (await import('./scenes/game.js')).default,
)
Inside scenes/game.js (or any lazily imported module), export a root Node as the default export:
// scenes/game.js
import { Node } from 'tiny-engine/nodes'

const root = new Node({ children: [] })

export default root

SceneManager

Every Game instance owns a SceneManager at Game.sceneManager. Use it to register scenes and switch between them at runtime.

addScene(name, scene, autoLoad?)

Registers a scene under a name. If the optional third argument is true, the scene is loaded immediately as well.
import { Game, Scene } from 'tiny-engine'

// Register without loading
Game.sceneManager.addScene(
  'main',
  new Scene(async () => (await import('./scenes/main.js')).default),
)

// Register and load right away (autoLoad = true)
await Game.sceneManager.addScene(
  'menu',
  new Scene(async () => (await import('./scenes/menu.js')).default),
  true,
)

setScene(name)

Switches to a previously registered scene. The current node tree is destroyed first, then the new scene is loaded and started. Pass null to unload the current scene without loading a new one.
await Game.sceneManager.setScene('main')

// Unload without switching
await Game.sceneManager.setScene(null)

preloadScene(name)

Preloads a scene in the background while the game is still running and returns a setter function you can call later to switch without any loading delay:
const setMainScene = await Game.sceneManager.preloadScene('main')

// ... later, switch instantly
setMainScene()

Game Lifecycle

Game.setup(options)

Game.setup() must be called before anything else. It creates the canvas element, appends it to the provided root element, and initialises the engine subsystems.
OptionTypeRequiredDescription
widthnumberCanvas width in pixels
heightnumberCanvas height in pixels
rootHTMLElementParent element the canvas is appended to
themeThemeDefault visual theme; a plain Theme instance is used if omitted
testOptionsPartial<TestOptions>Testing helpers (e.g. showClickables)
inputOptionsInputOptionsPointer and keyboard input configuration
import { Game } from 'tiny-engine'

const root = document.querySelector<HTMLElement>('#root')!

Game.setup({
  width: 320,
  height: 180,
  root,
})

Game.play()

Starts (or resumes) the game loop. Must be called after Game.setup(). Each frame the engine clears the canvas, calls update on the current scene’s node tree, resolves collisions, and calls draw.
await Game.sceneManager.addScene(
  'main',
  new Scene(async () => (await import('./scenes/main.js')).default),
  true,
)

Game.play()

Game.pause()

Suspends the game loop. The current frame finishes, then requestAnimationFrame is no longer scheduled. Call Game.play() to resume.
Game.pause()

Game.destroy()

Stops the game loop, removes all event listeners, destroys the current scene node tree, and resets all internal state so Game.setup() can be called again.
Game.destroy()

Auto-pause on Blur

tiny-engine automatically pauses the game when the browser window loses focus (window blur). The Game.blured event is emitted at that point. Once the user returns to the tab and calls Game.play(), the loop resumes.
import { Game } from 'tiny-engine'

Game.blured.on(() => {
  console.log('Window lost focus — game paused automatically')
})
Always call Game.destroy() when unmounting your game from the page — for example inside a framework’s cleanup callback. Failing to do so leaks the animation-frame loop, input event listeners, and wake-lock resources across navigations.

Build docs developers (and LLMs) love