Compare commits
2 Commits
c3e9eda702
...
1ee19b4b7f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ee19b4b7f | ||
|
|
394e8faef2 |
21
assets/_sources/_gen.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const { PNG } = require('pngjs');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
function writeSolidRGBA(p, w, h, rgba) {
|
||||
const png = new PNG({ width: w, height: h });
|
||||
for (let i = 0; i < png.data.length; i += 4) {
|
||||
png.data[i + 0] = rgba[0];
|
||||
png.data[i + 1] = rgba[1];
|
||||
png.data[i + 2] = rgba[2];
|
||||
png.data[i + 3] = rgba[3];
|
||||
}
|
||||
fs.writeFileSync(p, PNG.sync.write(png));
|
||||
}
|
||||
|
||||
const SOURCES = path.resolve(__dirname);
|
||||
writeSolidRGBA(path.join(SOURCES, 'demo_tilemap', 'grass_diffuse.png'), 32, 32, [110, 170, 80, 255]);
|
||||
writeSolidRGBA(path.join(SOURCES, 'demo_tilemap', 'stone_diffuse.png'), 32, 32, [120, 120, 120, 255]);
|
||||
writeSolidRGBA(path.join(SOURCES, 'walls_tilemap', 'wall_brick_diffuse.png'), 32, 32, [180, 100, 80, 255]);
|
||||
writeSolidRGBA(path.join(SOURCES, 'walls_tilemap', 'wall_wood_diffuse.png'), 32, 32, [140, 90, 50, 255]);
|
||||
console.log('test-stub sources generated');
|
||||
BIN
assets/_sources/demo_tilemap/grass_diffuse.png
Normal file
|
After Width: | Height: | Size: 128 B |
BIN
assets/_sources/demo_tilemap/stone_diffuse.png
Normal file
|
After Width: | Height: | Size: 125 B |
BIN
assets/_sources/walls_tilemap/wall_brick_diffuse.png
Normal file
|
After Width: | Height: | Size: 128 B |
BIN
assets/_sources/walls_tilemap/wall_wood_diffuse.png
Normal file
|
After Width: | Height: | Size: 128 B |
33
assets/atlases/demo_tilemap/tiles.atlas.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"atlas_id": "demo_tilemap",
|
||||
"atlas_version": 1,
|
||||
"atlas_size_px": [
|
||||
64,
|
||||
64
|
||||
],
|
||||
"tile_size_px": 32,
|
||||
"tiles": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "grass",
|
||||
"walkable": true,
|
||||
"uv": [
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
32
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "stone",
|
||||
"walkable": false,
|
||||
"uv": [
|
||||
32,
|
||||
0,
|
||||
32,
|
||||
32
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
9
assets/atlases/demo_tilemap/tiles.atlas.lock.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"atlas_id": "demo_tilemap",
|
||||
"bindings": {
|
||||
"grass": 1,
|
||||
"stone": 2
|
||||
},
|
||||
"deleted": [],
|
||||
"next_id": 3
|
||||
}
|
||||
BIN
assets/atlases/demo_tilemap/tiles.diffuse.atlas.png
Normal file
|
After Width: | Height: | Size: 162 B |
BIN
assets/atlases/demo_tilemap/tiles.height.atlas.png
Normal file
|
After Width: | Height: | Size: 176 B |
35
assets/atlases/walls_tilemap/tiles.atlas.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"atlas_id": "walls_tilemap",
|
||||
"atlas_version": 1,
|
||||
"atlas_size_px": [
|
||||
64,
|
||||
64
|
||||
],
|
||||
"tile_size_px": 32,
|
||||
"tiles": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "wall_brick",
|
||||
"walkable": false,
|
||||
"uv": [
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
32
|
||||
],
|
||||
"blocks_sight": true
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "wall_wood",
|
||||
"walkable": false,
|
||||
"uv": [
|
||||
32,
|
||||
0,
|
||||
32,
|
||||
32
|
||||
],
|
||||
"blocks_sight": true
|
||||
}
|
||||
]
|
||||
}
|
||||
9
assets/atlases/walls_tilemap/tiles.atlas.lock.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"atlas_id": "walls_tilemap",
|
||||
"bindings": {
|
||||
"wall_brick": 1,
|
||||
"wall_wood": 2
|
||||
},
|
||||
"deleted": [],
|
||||
"next_id": 3
|
||||
}
|
||||
BIN
assets/atlases/walls_tilemap/tiles.diffuse.atlas.png
Normal file
|
After Width: | Height: | Size: 161 B |
BIN
assets/atlases/walls_tilemap/tiles.height.atlas.png
Normal file
|
After Width: | Height: | Size: 176 B |
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"id": "demo_tilemap",
|
||||
"tile_size": 32,
|
||||
"tiles": [
|
||||
{"id": "grass", "walkable": true, "color": [110, 170, 80]},
|
||||
{"id": "stone", "walkable": false, "color": [120, 120, 120]}
|
||||
]
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"id": "walls_tilemap",
|
||||
"tile_size": 32,
|
||||
"tiles": [
|
||||
{"id": "wall_brick", "walkable": false, "color": [180, 100, 80]},
|
||||
{"id": "wall_wood", "walkable": false, "color": [140, 90, 50]}
|
||||
]
|
||||
}
|
||||
38
init.lua
@@ -8,6 +8,13 @@ local maps = require("lib-core.maps")
|
||||
local M = {}
|
||||
|
||||
function M.run_tests(ctx)
|
||||
-- Asset-aliases for texture-loading (test-libs lack manifest asset_aliases;
|
||||
-- hard-code the test-lib itself as the asset provider for its own atlases).
|
||||
local aliases = {
|
||||
demo_tilemap = "lib-core.maps-test",
|
||||
walls_tilemap = "lib-core.maps-test",
|
||||
}
|
||||
|
||||
-- ---------- Task 1: GID encode/decode ----------
|
||||
engine.test.equals(maps.encode_gid(0, 0, 0), 0, "encode_gid(0,0,0) = 0 (empty sentinel)")
|
||||
engine.test.equals(maps.encode_gid(0, 12, 0), 192, "encode_gid(0,12,0) = 192 (= 12<<4)")
|
||||
@@ -101,6 +108,7 @@ function M.run_tests(ctx)
|
||||
local v2_id = maps.load("maps/demo_v2.map.json")
|
||||
engine.test.equals(v2_id, "demo_v2", "v2 map loaded with id 'demo_v2'")
|
||||
maps.set_current(v2_id)
|
||||
maps.load_textures(aliases)
|
||||
local v2_size = maps.size()
|
||||
engine.test.equals(v2_size.w, 4, "v2 map width = 4")
|
||||
engine.test.equals(v2_size.h, 4, "v2 map height = 4")
|
||||
@@ -138,12 +146,12 @@ function M.run_tests(ctx)
|
||||
-- ---------- Task 6: Per-layer tile_at ----------
|
||||
-- tile_at_layer returns tile-record from the correct atlas
|
||||
local surface_tile = maps.tile_at_layer("surface", 1, 1)
|
||||
engine.test.assert(surface_tile ~= nil, "surface (1,1) returns tile")
|
||||
engine.test.equals(surface_tile.id, "grass", "surface (1,1) = grass")
|
||||
engine.test.assert(surface_tile ~= nil, "surface (1,1) returns tile")
|
||||
engine.test.equals(surface_tile.name, "grass", "surface (1,1) name = grass")
|
||||
|
||||
local wall_tile = maps.tile_at_layer("wall", 0, 0)
|
||||
engine.test.assert(wall_tile ~= nil, "wall (0,0) returns tile")
|
||||
engine.test.equals(wall_tile.id, "wall_brick", "wall (0,0) = wall_brick (from walls_tilemap)")
|
||||
engine.test.assert(wall_tile ~= nil, "wall (0,0) returns tile")
|
||||
engine.test.equals(wall_tile.name, "wall_brick", "wall (0,0) name = wall_brick (from walls_tilemap)")
|
||||
|
||||
-- Empty cell returns nil
|
||||
local empty_top = maps.tile_at_layer("topsurface", 0, 0)
|
||||
@@ -154,7 +162,7 @@ function M.run_tests(ctx)
|
||||
|
||||
-- Legacy tile_at backwards-compat: queries surface layer
|
||||
local legacy = maps.tile_at(1, 1)
|
||||
engine.test.equals(legacy.id, "grass", "legacy tile_at(x,y) queries surface layer")
|
||||
engine.test.equals(legacy.name, "grass", "legacy tile_at(x,y) queries surface layer")
|
||||
|
||||
-- ---------- Task 7: Gameplay queries ----------
|
||||
-- Surface-only cells (inside, no wall) → walkable
|
||||
@@ -205,36 +213,30 @@ function M.run_tests(ctx)
|
||||
local v1_id = maps.load("maps/demo.map.json")
|
||||
engine.test.equals(v1_id, "demo", "v1 demo map loaded")
|
||||
maps.set_current(v1_id)
|
||||
maps.load_textures(aliases)
|
||||
engine.test.equals(maps.atlas_count(), 1, "v1 auto-upgrade has 1 atlas")
|
||||
engine.test.equals(maps.atlas_id_at(0), "demo_tilemap", "v1 atlas[0] = demo_tilemap")
|
||||
engine.test.assert(maps.has_layer("surface"), "v1 auto-upgrade has surface layer")
|
||||
engine.test.assert(not maps.has_layer("wall"), "v1 has no wall layer")
|
||||
|
||||
-- Walkability via v2-API should match v1-API result
|
||||
-- Walkability via v2-API should match v1-API result (atlas records now loaded)
|
||||
engine.test.assert(maps.is_walkable(5, 5), "v1 (5,5) walkable (was grass in v1 test)")
|
||||
engine.test.assert(not maps.is_walkable(0, 0), "v1 (0,0) not walkable (was stone in v1 test)")
|
||||
|
||||
-- Restore current to v2 map for subsequent tests if any
|
||||
maps.set_current("demo_v2")
|
||||
|
||||
-- Setup (legacy demo assertions, now using already-loaded demo from Task 9 above)
|
||||
local demo_map = "demo"
|
||||
maps.set_current(demo_map)
|
||||
|
||||
-- Geometry assertions
|
||||
-- Geometry assertions (demo map, already current after load_textures block)
|
||||
local size = maps.size()
|
||||
engine.test.equals(size.w, 16, "map width = 16")
|
||||
engine.test.equals(size.h, 16, "map height = 16")
|
||||
engine.test.equals(maps.tile_size(), 32, "tile_size = 32")
|
||||
|
||||
-- Tile lookup + walkability
|
||||
engine.test.equals(maps.tile_at(0, 0).id, "stone", "tile_at(0,0) is stone")
|
||||
engine.test.equals(maps.tile_at(5, 5).id, "grass", "tile_at(5,5) is grass")
|
||||
-- Tile lookup + walkability (post-M.2: tile.id is int, tile.name is string)
|
||||
engine.test.equals(maps.tile_at(0, 0).name, "stone", "tile_at(0,0) name = stone")
|
||||
engine.test.equals(maps.tile_at(5, 5).name, "grass", "tile_at(5,5) name = grass")
|
||||
engine.test.assert(not maps.is_walkable(0, 0), "stone border non-walkable")
|
||||
engine.test.assert(maps.is_walkable(5, 5), "grass interior walkable")
|
||||
|
||||
-- Arity-flex tile_at: 3-arg with nil map_id falls back to current_map (P.2.1)
|
||||
engine.test.equals(maps.tile_at(nil, 5, 5).id, "grass", "tile_at 3-arg nil-fallback")
|
||||
engine.test.equals(maps.tile_at(nil, 5, 5).name, "grass", "tile_at 3-arg nil-fallback name = grass")
|
||||
|
||||
-- Out-of-bounds returns nil
|
||||
engine.test.equals(maps.tile_at(-1, 0), nil, "tile_at OOB negative tx returns nil")
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"id": "lib-core.maps-test",
|
||||
"role": "test",
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"api_min": "0.1",
|
||||
"deps": [
|
||||
{"id": "lib-core.maps", "version": "0.2.0"}
|
||||
{"id": "lib-core.maps", "version": "0.3.0"}
|
||||
]
|
||||
}
|
||||
|
||||
19
scripts/bake.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
# Re-bake the stub atlases used by maps-test fixtures.
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LIB_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
BAKER=~/Projects/Sporel/sporel-tool-atlas-baker/bin/atlas-baker.js
|
||||
|
||||
node "$BAKER" \
|
||||
--in "$LIB_DIR/assets/_sources/demo_tilemap" \
|
||||
--out "$LIB_DIR/assets/atlases/demo_tilemap" \
|
||||
--atlas-id demo_tilemap \
|
||||
--tile-size 32
|
||||
|
||||
node "$BAKER" \
|
||||
--in "$LIB_DIR/assets/_sources/walls_tilemap" \
|
||||
--out "$LIB_DIR/assets/atlases/walls_tilemap" \
|
||||
--atlas-id walls_tilemap \
|
||||
--tile-size 32 \
|
||||
--blocks-sight-pattern '^wall_'
|
||||