feat(ecs): Light2D/Occluder/Ambient as auto-consumed components (#47)
The ECS-native shape the 2D lighting follow-up asked for, built on the engine-owned-system hook from #43. A torch is just an entity carrying Light2D, a wall an entity carrying Occluder, and one Ambient entity sets the night tint — the engine runs the whole deterministic light pass at the end of the Render phase (ambient modulate -> carve occluder shadows -> accumulate additive radial lights) and presents. No Light.* calls wired. - runtime/native/systems_light.ludic: esys_light2d, consuming the components through the by-name reflection ABI and reusing the #4 accumulation core (light_ambient / light_occlude / light_point). Reads position from a Position component when present, else the light's own x/y. - Split from systems.ludic so a SpriteAnim/Motion-only game never links the light pass; spliced (with light.ludic) only when Light2D/Occluder declared. - emit_main now boots rt_init like the auto-loop/test runner, so an entry-driven game that renders has its framebuffer allocated (headless: allocate only, no window, byte-identical stdout for non-rendering games). Worked example + regression: examples/library/light_ecs.ludic (32 1 32 1). Full suite 74 passed, self-host C-free fixpoint intact, no golden drift. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b0143337d9
commit
3679ce1797
8 changed files with 14660 additions and 14404 deletions
|
|
@ -246,6 +246,10 @@ function cmd_test() -> int {
|
|||
# game merely declares and carries — no handler wired. Entry-driven so it can
|
||||
# assert the auto-advanced fields at known tick counts.
|
||||
net_case("library/anim_ecs", "1 5 2 10 0 2 10 1 1")
|
||||
# #47: the engine light pass consumes Light2D / Occluder / Ambient components at
|
||||
# the end of the Render phase — ambient tint, additive glow, hard shadow — with
|
||||
# no Light.* calls wired. Sampled back off the framebuffer with Screen.pixel.
|
||||
net_case("library/light_ecs", "32 1 32 1")
|
||||
|
||||
feat_case("events/recurse", "", "16", "recurse.ludic (EV6: re-entrant emit is depth-bounded, no runaway cycle)")
|
||||
net_case("events/scoped", "2")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue