Files
dusk/.claude/scene.md
T
2026-06-16 10:15:59 -05:00

111 lines
3.2 KiB
Markdown

# 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)
```c
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:
1. Checks for a pending scene transition and performs it (dispose old,
load and init new).
2. Calls the JS scene's `update()` hook.
3. Calls `entityManagerUpdate()` to fire all entity update callbacks.
`sceneRender` each tick:
1. Binds the screen.
2. Calls `sceneRenderPipeline()` -- renders all entities with a
`COMPONENT_TYPE_RENDERABLE` in priority order.
3. Renders UI.
4. Calls the JS scene's `render()` hook (for any custom drawing).
5. Unbinds the screen.
## Scene lifecycle (JS side)
A scene file exports a plain object with these optional hooks:
```js
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_SPRITEBATCH` and `CUSTOM` default to
`SHADER_LIST_SHADER_UNLIT`.
- `ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL` uses the shader indexed by
`renderable.data.material.shaderType` in `SHADER_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
```