Parent: #126
Problem
Bloom has a broad raylib-like flat API and world/prefab data, but lacks a small Unity-like behavior/lifecycle layer tying entities, transforms, rendering, physics, animation, audio, serialization, and updates together. Games otherwise create their own conventions, duplicate cleanup and handle bookkeeping, and become difficult to compose.
Outcome
An optional, thin TypeScript component/entity facade over existing low-level APIs. It should make common scene behavior familiar and composable without forcing ECS complexity or removing immediate-mode usage.
Public model
Define:
- stable
Entity identity with hierarchical transform;
- typed components with explicit ownership and serialization IDs;
- lifecycle hooks such as
onCreate, onStart, onUpdate, onFixedUpdate, onEnable, onDisable, onDestroy (exact names may vary);
- deterministic update order and a supported dependency/order mechanism;
- scene/prefab instantiate/destroy with cleanup of native handles;
- component lookup that is type-safe within Perry's supported TypeScript subset;
- bridges for renderer/model, camera/light, rigid body/collider, animator, audio source/listener, and user scripts.
The minimum game should still fit in a short file. Low-level draw* and handle APIs remain available.
Ownership and lifecycle rules
- State whether entity or component owns each native handle.
- Destruction is idempotent and happens at a safe frame boundary.
- Parent destroy, reparent, enable/disable, scene unload, and async asset completion have deterministic behavior.
- Fixed physics updates are separated from variable render updates with interpolation rules.
- A component cannot receive update after destruction or before required dependencies are ready.
- Errors include entity/component names/IDs rather than only native handles.
Serialization/prefabs
- Register component type/version and encode stable data only; runtime handles are reconstructed.
- Unknown component versions/types survive or fail according to a documented forward-compatibility policy.
- Prefab override semantics are explicit and tested.
- User scripts can define serializable fields within the Perry-supported type subset.
Acceptance criteria
Likely files
- new module under
src/ (for example src/components/ or src/game/)
src/world/ prefab/serialization/version code
- existing scene/models/physics/audio wrappers
- small native support only where lifecycle-safe batching cannot be expressed through current FFI
Non-goals
- A data-oriented ECS rewrite of the native engine.
- Editor reflection/inspector UI.
- Replacing the raylib-style API.
Dependencies
Parent: #126
Problem
Bloom has a broad raylib-like flat API and world/prefab data, but lacks a small Unity-like behavior/lifecycle layer tying entities, transforms, rendering, physics, animation, audio, serialization, and updates together. Games otherwise create their own conventions, duplicate cleanup and handle bookkeeping, and become difficult to compose.
Outcome
An optional, thin TypeScript component/entity facade over existing low-level APIs. It should make common scene behavior familiar and composable without forcing ECS complexity or removing immediate-mode usage.
Public model
Define:
Entityidentity with hierarchical transform;onCreate,onStart,onUpdate,onFixedUpdate,onEnable,onDisable,onDestroy(exact names may vary);The minimum game should still fit in a short file. Low-level
draw*and handle APIs remain available.Ownership and lifecycle rules
Serialization/prefabs
Acceptance criteria
Likely files
src/(for examplesrc/components/orsrc/game/)src/world/prefab/serialization/version codeNon-goals
Dependencies