ludic/changes
Orkuncakilkaya 3679ce1797
All checks were successful
bootstrap / cfree-fixpoint (push) Successful in 18s
ci / build-and-test (push) Successful in 1m18s
commit-lint / conventional-commits (push) Successful in 4s
docs / build-and-deploy (push) Successful in 19s
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>
2026-08-31 15:49:50 +03:00
..
coverage.md feat(testing): line coverage via --coverage + bin/x test --coverage (#45) 2026-08-31 14:51:14 +03:00
engine-systems.md feat(ecs): engine-owned systems auto-tick user components (#43) 2026-08-31 15:41:44 +03:00
error-handling.md feat(errors): panic(msg) + assert(cond, msg) with file:line — no raw crashes (#8) 2026-08-31 14:33:37 +03:00
light-ecs-components.md feat(ecs): Light2D/Occluder/Ambient as auto-consumed components (#47) 2026-08-31 15:49:50 +03:00
light-namespace.md feat(rendering): add Light.* — deterministic 2D light accumulation with hard shadows (#4) 2026-08-31 14:07:19 +03:00
README.md feat(release): SemVer + ludicc --version, changesets, and x release 2026-08-30 23:46:59 +03:00
recover.md feat(errors): recoverable failures as values — try/else over ok/err results (#46) 2026-08-31 15:04:14 +03:00
testing-framework.md feat(testing): built-in test blocks + expect assertions, auto-run with pass/fail (#12) 2026-08-31 14:27:45 +03:00
value-tree.md feat(reflect): generic value tree + Reflect.serialize/apply + JSON bridge (#44) 2026-08-31 15:19:21 +03:00

Changesets

A changeset is one small Markdown file describing a single user-facing change, dropped in this directory. x release consumes every changeset here into a new CHANGELOG.md section, bumps VERSION, and deletes the consumed files.

Format

bump: minor
type: feat
One or more lines describing the change, in the past-agnostic imperative used in
the changelog. Markdown is fine.
  • bump: — major, minor, or patch (SemVer). The release version is bumped by the highest level among the pending changesets (unless x release <level> overrides it).
  • type: — the Conventional Commit type (feat, fix, perf, docs, …); it becomes the bold prefix of the changelog bullet.

Adding one

Create a file with a short, unique name, e.g. changes/regex-namespace.md. Any filename works except this README.md, which the release step always skips.