3.2 KiB
Scene System
Source: src/dusk/scene/
Overview
The scene system is the top-level coordinator for a running game state.
It manages one active scene at a time. Scenes are JS scripts -- each
scene is a .js asset file that exports an object with lifecycle hooks.
The scene system loads, ticks, and tears down these scripts, while the
C side runs the ECS and render pipeline on each tick.
Scene lifecycle (C side)
extern scene_t SCENE;
errorret_t sceneInit(void); // initialise the scene manager
errorret_t sceneUpdate(void); // process pending transition, tick active scene
errorret_t sceneRender(void); // render entities + render pipeline + UI
errorret_t sceneDispose(void); // dispose the active scene immediately
sceneUpdate each tick:
- Checks for a pending scene transition and performs it (dispose old, load and init new).
- Calls the JS scene's
update()hook. - Calls
entityManagerUpdate()to fire all entity update callbacks.
sceneRender each tick:
- Binds the screen.
- Calls
sceneRenderPipeline()-- renders all entities with aCOMPONENT_TYPE_RENDERABLEin priority order. - Renders UI.
- Calls the JS scene's
render()hook (for any custom drawing). - Unbinds the screen.
Scene lifecycle (JS side)
A scene file exports a plain object with these optional hooks:
var scene = {};
scene.init = async function() {
// Load assets, create entities, set up state.
// May be async -- await asset loads here.
};
scene.update = function() {
// Called each fixed-timestep tick.
};
scene.render = function() {
// Called each render tick, after ECS renderables.
};
scene.dispose = function() {
// Clean up entities and state.
};
module.exports = scene;
See CLAUDE.md -- "JavaScript (asset scripts)" for JS style rules.
Render pipeline (scenerenderpipeline.h)
sceneRenderPipeline(cameraEntityId) gathers all active
COMPONENT_TYPE_RENDERABLE components, sorts them by effective
priority, and draws each one using its shader.
Priority rules:
renderable.priority != 0-- use that value directly.renderable.priority == 0-- auto-derive: opaque geometry sorts before transparent geometry; sprite batches sort before shader materials; etc.- Lower priority number = drawn first (behind); higher = drawn last (on top).
The shader used for each renderable:
ENTITY_RENDERABLE_TYPE_SPRITEBATCHandCUSTOMdefault toSHADER_LIST_SHADER_UNLIT.ENTITY_RENDERABLE_TYPE_SHADER_MATERIALuses the shader indexed byrenderable.data.material.shaderTypeinSHADER_LIST_DEFS.
Transitioning between scenes
To move to a new scene from JS, call the scene module's transition
function (exact API in the scene JS module). The C side defers the
actual switch to the start of the next sceneUpdate call so the
current tick completes cleanly before any dispose runs.
Relationship to the engine loop
engineUpdate()
timeUpdate()
inputUpdate()
physicsManagerUpdate()
scriptUpdate() <- runs JS microjobs
sceneUpdate() <- JS update + ECS entity updates
engineUpdate() -> sceneRender()
screenBind()
sceneRenderPipeline() <- ECS renderables sorted by priority
uiRender()
sceneRender (JS hook)
screenUnbind / screenRender