feat: v0.1.2 sprite-mode in draw_map + tile_rotations + load_textures
Sprite-mode in draw_map: - tilemap-tiles with texture atlas-id render via engine.render.draw_sprite_transform with rotation pivot at tile center - tiles without texture continue to render via draw_rect with color (Phase 1 mode preserved) Tile rotation: - maps support an optional tile_rotations parallel array in the map JSON with per-cell 90-degree rotation values (0/90/180/270) - absent or nil entries default to 0 (no rotation) - enables 9-segment tile reuse via rotation rather than per-orientation sprites New API: - maps.load_textures(asset_aliases) resolves the current tilemap's tile atlas-ids to texture-handles via the asset-lib indirection (asset_aliases[tilemap.asset_pack] -> lib-id -> atlas.json lookup per tile) Schema additions: - tilemap.asset_pack (alias-key, optional) - tile.texture (atlas-id, optional) - map.tile_rotations (parallel array, optional) All existing Phase 1 color-only tilemaps render unchanged.
This commit is contained in:
33
README.md
33
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
Single tile-grid map implementation. Loads JSON map + tilemap files, registers maps by id, and provides tile-fetch + walkability + size queries with current-map sugar.
|
||||
|
||||
**Version:** 0.1.1
|
||||
**Version:** 0.1.2
|
||||
**Lib-ID:** lib-core.maps
|
||||
**Requires:** (none)
|
||||
**Tags:** maps, tile-grid, walkability, tilemap
|
||||
@@ -93,6 +93,22 @@ if tile then engine.print(tile.id) end
|
||||
|
||||
**Description:** Returns an array of all registered map-ids.
|
||||
|
||||
### `maps.load_textures(asset_aliases)`
|
||||
**Syntax:** `maps.load_textures(asset_aliases: {[string]: string}) -> void`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
maps.set_current(map_id)
|
||||
maps.load_textures({ terrain = "lib-core.terrain-assets" })
|
||||
```
|
||||
|
||||
**Description:** Resolves the current tilemap's tile `texture` atlas-ids to texture-handles via the asset-lib indirection. `asset_aliases` maps the tilemap's `asset_pack` alias-key to a lib-id; the lib's `assets/atlas.json` is read to locate each texture file. Populates `tile.texture_handle` on each tile in-place. No-op if the tilemap has no `asset_pack`. Call once at module init after `set_current`; do not call repeatedly (texture handles are not auto-cached).
|
||||
|
||||
### `maps.draw_map()`
|
||||
**Syntax:** `maps.draw_map() -> void`
|
||||
|
||||
**Description:** Draws the current map grid. Tiles with a resolved `texture_handle` render via `engine.render.draw_sprite_transform` with rotation about the tile center (using the map's optional `tile_rotations` parallel array). Tiles without a texture handle fall back to `engine.render.draw_rect` with `tile.color` (Phase 1 mode). No-op if no current map.
|
||||
|
||||
### `maps.state(map_id)`
|
||||
**Syntax:** `maps.state(map_id: string) -> string`
|
||||
|
||||
@@ -130,6 +146,21 @@ end
|
||||
|
||||
## CHANGELOG
|
||||
|
||||
### v0.1.2
|
||||
- Sprite-mode in draw_map: tilemap-tiles with `texture` atlas-id render
|
||||
via engine.render.draw_sprite_transform; tiles without `texture` fall
|
||||
back to color-rect render (Phase 1 mode).
|
||||
- Map-data tile_rotations parallel array support: per-cell 90-degree
|
||||
rotation in {0, 90, 180, 270}, applied at draw via rotation about
|
||||
the tile center. Optional; absent means all-zero.
|
||||
- New API: maps.load_textures(asset_aliases) resolves the current
|
||||
tilemap's tile atlas-ids to texture-handles via the asset-lib
|
||||
indirection. Mirrors the puppet.load_textures pattern.
|
||||
- Tilemap schema additions: tilemap.asset_pack (alias-key),
|
||||
tile.texture (atlas-id).
|
||||
- Backward-compat: existing Phase 1 color-only tilemaps render
|
||||
unchanged.
|
||||
|
||||
### v0.1.1
|
||||
- Tilemap-id resolution handles module-ids with dots (prefix-match instead of first-dot split).
|
||||
|
||||
|
||||
85
init.lua
85
init.lua
@@ -96,10 +96,22 @@ local function load_tilemap(full_id)
|
||||
local path = "assets/tiles/" .. local_name .. ".tilemap.json"
|
||||
local raw = engine.asset.load_json(path)
|
||||
validate_tilemap_table(raw, path, local_name)
|
||||
-- Cook tiles: copy raw fields and add texture + texture_handle slots.
|
||||
local cooked = {}
|
||||
for i, t in ipairs(raw.tiles) do
|
||||
cooked[i] = {
|
||||
id = t.id,
|
||||
walkable = (t.walkable == true),
|
||||
color = t.color, -- color-mode fallback
|
||||
texture = t.texture, -- optional atlas-id
|
||||
texture_handle = nil, -- populated by load_textures
|
||||
}
|
||||
end
|
||||
local tilemap = {
|
||||
id = full_id,
|
||||
tile_size = raw.tile_size,
|
||||
tiles = raw.tiles,
|
||||
asset_pack = raw.asset_pack, -- optional alias-key
|
||||
tiles = cooked,
|
||||
}
|
||||
tilemap_registry[full_id] = tilemap
|
||||
return tilemap
|
||||
@@ -118,6 +130,7 @@ local function build_map(t_map, tilemap)
|
||||
size = t_map.size,
|
||||
tile_size = t_map.tile_size or tilemap.tile_size,
|
||||
tiles = t_map.tiles, -- shallow-ref
|
||||
tile_rotations = t_map.tile_rotations, -- optional parallel array (NEW)
|
||||
tilemap = tilemap, -- shallow-ref
|
||||
-- DEPRECATED-MVP: forward-compat stubs (multi-map slice fills)
|
||||
walls = {},
|
||||
@@ -227,6 +240,76 @@ function M.list()
|
||||
return out
|
||||
end
|
||||
|
||||
-- ====================================================================
|
||||
-- Resolve tilemap-tile atlas-ids to texture-handles via asset-lib.
|
||||
-- Operates on the current map's tilemap; call after maps.set_current.
|
||||
-- asset_aliases: { [alias-key] = asset-lib-id } from module's manifest.
|
||||
-- ====================================================================
|
||||
function M.load_textures(asset_aliases)
|
||||
local map_id = M.current()
|
||||
if map_id == nil then
|
||||
error("maps.load_textures: no current map; call maps.set_current first")
|
||||
end
|
||||
local m = map_registry[map_id]
|
||||
local tm = m.tilemap
|
||||
if tm.asset_pack == nil then return end -- color-only tilemap, no textures
|
||||
local lib_id = asset_aliases[tm.asset_pack]
|
||||
if lib_id == nil then
|
||||
error("maps.load_textures: asset-pack alias '" .. tm.asset_pack
|
||||
.. "' not in asset_aliases")
|
||||
end
|
||||
local atlas_path = lib_id .. "/assets/atlas.json"
|
||||
local atlas = engine.asset.load_json(atlas_path)
|
||||
local pack = atlas[tm.asset_pack]
|
||||
if pack == nil then
|
||||
error("maps.load_textures: asset_pack '" .. tm.asset_pack
|
||||
.. "' not declared in atlas of '" .. lib_id .. "'")
|
||||
end
|
||||
for _, tile in ipairs(tm.tiles) do
|
||||
if tile.texture then
|
||||
local entry = pack[tile.texture]
|
||||
if entry == nil then
|
||||
error("maps.load_textures: atlas-id '" .. tile.texture
|
||||
.. "' not in asset_pack '" .. tm.asset_pack .. "'")
|
||||
end
|
||||
tile.texture_handle = engine.asset.load_texture(lib_id .. "/assets/" .. entry.file)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.draw_map()
|
||||
local map_id = M.current()
|
||||
if map_id == nil then return end
|
||||
local m = map_registry[map_id]
|
||||
local tm = m.tilemap
|
||||
local ts = tm.tile_size
|
||||
for y = 0, m.size.h - 1 do
|
||||
for x = 0, m.size.w - 1 do
|
||||
local idx = y * m.size.w + x + 1
|
||||
local tile_id = m.tiles[idx]
|
||||
local tile = tm.tiles[tile_id]
|
||||
local rot_deg = (m.tile_rotations and m.tile_rotations[idx]) or 0
|
||||
local px = x * ts
|
||||
local py = y * ts
|
||||
if tile.texture_handle then
|
||||
-- Sprite mode: draw_sprite_transform with rotation about tile center.
|
||||
engine.render.draw_sprite_transform(
|
||||
tile.texture_handle,
|
||||
px + ts / 2, py + ts / 2,
|
||||
math.rad(rot_deg),
|
||||
1.0, 1.0,
|
||||
ts / 2, ts / 2,
|
||||
0xFFFFFFFF
|
||||
)
|
||||
else
|
||||
-- Color fallback (Phase 1 mode).
|
||||
local c = tile.color or { 100, 100, 100 }
|
||||
engine.render.draw_rect(px, py, ts, ts, engine.render.rgb(c[1], c[2], c[3]))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Forward-compat stubs (DEPRECATED-MVP — implemented in later slices)
|
||||
function M.state(map_id)
|
||||
-- DEPRECATED-MVP: lifecycle states (Virgin/Inert/Passive/Active/Pinned) — multi-map slice
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"id":"lib-core.maps","version":"0.1.1","api_min":"0.1"}
|
||||
{"id":"lib-core.maps","version":"0.1.2","api_min":"0.1"}
|
||||
|
||||
Reference in New Issue
Block a user