ludic/examples/library/sprite_atlas.ludic
Orkuncakilkaya 19fcf60599 wip(0.S3): packages and examples migrated again from their pre-0.S sources in one run
ludic migrate state packages <every example program> packages/ludic.lab/example/plate.ludic
  1804 vars into 126 states, 64 into lets; 23498 edits in 460 files

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:31:34 +03:00

53 lines
2.5 KiB
Text

# sprite_atlas.ludic — the engine sprite-render system draws atlas ids (#90).
# `Sprite { id, atlas: 1 }` marks `id` as a Sprite.cell / Sprite.cell_span sprite
# (any size, here a 16x32 two-cell character) and esys_sprite routes it through
# atlas_draw_ex with scale / flip / tint, so the #81 atlas API and the #85 engine
# sprite system compose. atlas: 0 (the default) keeps `id` a 16x16 table sprite.
# Verified by pixel readback after one frame.
#
# Driven headless by one stdin key ('q' quits after the frame renders).
# printf 'q' | LUDIC_MODULES=packages bin/ludic examples/library/sprite_atlas.ludic -> 32 1 1 1 0
program SpriteAtlas {
import "ludic.core/components.ludic"
state SpriteAtlasState {
TALL: int = 0
}
function bi(b: bool) -> int { if b { return 1 }; return 0 }
@OnStart handler Boot(sprite_atlas_st: mut SpriteAtlasState) {
let sheet = Sprite.sheet("assets/kenney/tiny-dungeon/Tilemap/tilemap_packed.png", 16, 16)
sprite_atlas_st.TALL = Sprite.cell_span(sheet, 0, 0, 1, 2) # a 16x32 sprite: two cells tall
spawn Tall { Position { x: 40, y: 40 }, Sprite { id: sprite_atlas_st.TALL, atlas: 1 } }
spawn Tinted { Position { x: 100, y: 40 }, Sprite { id: sprite_atlas_st.TALL, atlas: 1, tint: 0xff0000 } }
spawn Table { Position { x: 160, y: 40 }, Sprite { id: sprite_atlas_st.TALL } } # atlas: 0 -> the (empty) 16x16 table
}
# An empty Render handler: the engine sprite system draws the Sprite entities.
handler Draw phase Render { }
@OnQuit handler Report(sprite_atlas_st: SpriteAtlasState) {
print(Sprite.height(sprite_atlas_st.TALL)) # 32 — the span is two cells tall
var top = 0
for yy in 40 .. 56 { for xx in 40 .. 56 { if Screen.pixel(xx, yy) != 0 { top = 1 } } }
print(top) # 1 — the upper cell drew
var bottom = 0
for yy in 56 .. 72 { for xx in 40 .. 56 { if Screen.pixel(xx, yy) != 0 { bottom = 1 } } }
print(bottom) # 1 — the lower cell drew too (a table sprite stops at 16px)
var tinted = 1
var seen = 0
for yy in 40 .. 72 { for xx in 100 .. 116 {
let c = Screen.pixel(xx, yy)
if c != 0 { seen = 1; if c != 0xff0000 { tinted = 0 } }
} }
print(bi((seen == 1) and (tinted == 1))) # 1 — every opaque pixel took the tint
var table = 0
for yy in 40 .. 72 { for xx in 160 .. 176 { if Screen.pixel(xx, yy) != 0 { table = 1 } } }
print(table) # 0 — without atlas: 1 the id is a table id (nothing loaded there)
}
}