ludic/examples/library/preload.ludic
Orkuncakilkaya f2cb3cd7e8
All checks were successful
bootstrap / cfree-fixpoint (push) Successful in 22s
ci / build-and-test (push) Successful in 2m27s
commit-lint / conventional-commits (push) Successful in 5s
docs / build-and-deploy (push) Successful in 28s
feat(assets): #82 incremental asset preloading + loading-scene pattern
Assets loaded synchronously in Boot stalled the first frame(s). Adds an
Assets.* preload queue over the #81 atlas: Assets.enqueue(name, path) queues a
named image without loading it, Assets.pump(max) loads up to max per frame
(returns how many), and Assets.total/loaded/ready/progress (0..100) drive a
progress bar. A loading scene pumps a few per frame, draws Assets.progress(),
and becomes the play scene once Assets.ready() — the deterministic, no-threads
form of async preloading (work spread across frames; same enqueue+pump order
loads identically every run). Loaded assets are reachable by name via
Assets.get / Sprite.named.

Example preload (enqueue 3, pump incrementally 0->33->66->100, ready flips, get
by name) prints 3 0 0 0 1 33 66 1 100 1. 6 docs pages. Full suite 117/0,
fixpoint holds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 08:19:19 +03:00

38 lines
1.7 KiB
Text

# preload.ludic — incremental asset preloading (#82). Instead of loading every
# asset synchronously in Boot (stalling the first frame), enqueue named files and
# load a bounded number per frame with Assets.pump, showing progress until
# Assets.ready(). Deterministic (no threads): the work is spread across frames.
#
# The loading-scene pattern: in a `scene Loading` a Render handler pumps a few
# assets, draws Assets.progress() as a bar, and `become`s the play scene once
# Assets.ready(). Here the API is driven from `entry` for a deterministic check.
#
# Deterministic; a full run prints: 3 0 0 0 1 33 66 1 100 1
program Preload {
# a model so the program runs the ECS and links the core runtime / framebuffer.
property Cam { z: fixed = 1.0 }
model V { Cam }
function bi(b: bool) -> int { if b { return 1 }; return 0 }
entry {
Assets.enqueue("hero", "assets/kenney/tiny-dungeon/Tiles/tile_0096.png")
Assets.enqueue("wall", "assets/kenney/tiny-dungeon/Tiles/tile_0036.png")
Assets.enqueue("door", "assets/kenney/tiny-dungeon/Tiles/tile_0037.png")
print(Assets.total()) # 3
print(Assets.loaded()) # 0
print(Assets.progress()) # 0
print(bi(Assets.ready())) # 0
Assets.pump(1) # load one this frame
print(Assets.loaded()) # 1
print(Assets.progress()) # 33
Assets.pump(1) # and one the next
print(Assets.progress()) # 66
Assets.pump(5) # drain the rest
print(bi(Assets.ready())) # 1
print(Assets.progress()) # 100
print(bi(Assets.get("hero") >= 0)) # 1 — reachable by name once loaded
}
}