feat(iso): rich Kenney Isometric Dungeon set + correct facing + ASCII picker
A — RICH ISO. The old iso-dungeon was a 7-tile sliver of Kenney Isometric Dungeon; wire the full set so town/dungeon are RICH and interchangeable: - Real architecture: full stoneWall, stoneWallWindow (actual window), stoneWallDoorOpen (real door), archway, wood column, stairs. - Distinct furniture per kind: table -> tableShortChairs (table+chairs), keg/barrel -> real barrel, crate -> woodenCrate, shelf -> woodenCrates, chest -> chestClosed (added to the floor+prop compositor). No more everything-is-a-chest. Facing (was 90 deg off, twice): verified against live movement the sprites are angled CLOCKWISE from NE (0=NE,2=SE,4=SW,6=NW), so up->Male_0, right->Male_2, down->Male_4, left->Male_6. Now the run anim points the way you actually move. ASCII picker no-op: ASCII draws glyphs and consumes no tile pack, so projForMode(ascii)=null and the packbar hides for it (it only ever made sense for Tiled/Iso). Suite 58/419 green.
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
@@ -288,32 +288,40 @@
|
||||
avatar: 'char-villager',
|
||||
tile: { w: 84, h: 42, imageW: 92, imageH: 184 },
|
||||
tiles: {
|
||||
floor: 'assets/kenney/iso-dungeon/tiles/planks_S.png',
|
||||
floor2: 'assets/kenney/iso-dungeon/tiles/stone_S.png',
|
||||
wall: 'assets/kenney/iso-dungeon/tiles/stoneWallHalf_S.png', // half walls keep the interior visible
|
||||
window: 'assets/kenney/iso-dungeon/tiles/stoneWallHalf_S.png', // no iso window art — reuse the half wall
|
||||
// Floors / ground
|
||||
floor: 'assets/kenney/iso-dungeon/tiles/planks_S.png', // wood — tavern interior
|
||||
floor2: 'assets/kenney/iso-dungeon/tiles/stone_S.png', // stone — dungeon
|
||||
dirt: 'assets/kenney/iso-dungeon/tiles/dirt_S.png',
|
||||
rug: 'assets/kenney/iso-dungeon/tiles/planks_S.png',
|
||||
door: 'assets/kenney/iso-dungeon/tiles/planks_S.png',
|
||||
// Furniture props (drawn over a floor base):
|
||||
bar: 'assets/kenney/iso-dungeon/tiles/barrelsStacked_S.png', // stacked kegs = the bar
|
||||
keg: 'assets/kenney/iso-dungeon/tiles/barrelsStacked_S.png',
|
||||
barrel: 'assets/kenney/iso-dungeon/tiles/barrelsStacked_S.png',
|
||||
shelf: 'assets/kenney/iso-dungeon/tiles/chestClosed_S.png',
|
||||
table: 'assets/kenney/iso-dungeon/tiles/chestClosed_S.png',
|
||||
crate: 'assets/kenney/iso-dungeon/tiles/chestClosed_S.png',
|
||||
// Architecture (full-height tiles). The rich set has real windows/doors/archways.
|
||||
wall: 'assets/kenney/iso-dungeon/tiles/stoneWall_S.png',
|
||||
window: 'assets/kenney/iso-dungeon/tiles/stoneWallWindow_S.png',
|
||||
door: 'assets/kenney/iso-dungeon/tiles/stoneWallDoorOpen_S.png',
|
||||
archway:'assets/kenney/iso-dungeon/tiles/stoneWallArchway_S.png',
|
||||
column: 'assets/kenney/iso-dungeon/tiles/stoneColumnWood_S.png',
|
||||
stairs: 'assets/kenney/iso-dungeon/tiles/stairs_S.png',
|
||||
// Furniture props (drawn over a floor base) — each kind now has distinct art.
|
||||
bar: 'assets/kenney/iso-dungeon/tiles/barrelsStacked_S.png', // stacked barrels = the bar counter
|
||||
keg: 'assets/kenney/iso-dungeon/tiles/barrel_S.png',
|
||||
barrel: 'assets/kenney/iso-dungeon/tiles/barrel_S.png',
|
||||
table: 'assets/kenney/iso-dungeon/tiles/tableShortChairs_S.png', // real table + chairs
|
||||
shelf: 'assets/kenney/iso-dungeon/tiles/woodenCrates_S.png',
|
||||
crate: 'assets/kenney/iso-dungeon/tiles/woodenCrate_S.png',
|
||||
chair: 'assets/kenney/iso-dungeon/tiles/chair_S.png',
|
||||
chest: 'assets/kenney/iso-dungeon/tiles/chestClosed_S.png',
|
||||
fallback: 'assets/kenney/iso-dungeon/tiles/planks_S.png'
|
||||
},
|
||||
// The Kenney files named Male_0..Male_7 are directional renders of the same body,
|
||||
// not different character classes. The customizer exposes one honest Iso body for now.
|
||||
// Kenney Male_0..7 are 45° renders (0=NW, 2=SW, 4=SE, 6=NE). In this iso projection a grid
|
||||
// step moves visually: up->NE, down->SW, left->NW, right->SE — so face the way you move.
|
||||
character: isoMale(2),
|
||||
// These sprites are angled CLOCKWISE from NE: 0=NE, 2=SE, 4=SW, 6=NW (verified against live
|
||||
// movement). In this iso projection a grid step moves visually up->NE, down->SW, left->NW,
|
||||
// right->SE, so each facing uses the sprite pointing that way — face the way you move.
|
||||
character: isoMale(3), // idle faces roughly toward the camera (S)
|
||||
directions: {
|
||||
down: isoMale(2), // SW (down-left)
|
||||
up: isoMale(6), // NE (up-right)
|
||||
left: isoMale(0), // NW (up-left)
|
||||
right: isoMale(4) // SE (down-right)
|
||||
up: isoMale(0), // NE (up-right)
|
||||
down: isoMale(4), // SW (down-left)
|
||||
left: isoMale(6), // NW (up-left)
|
||||
right: isoMale(2) // SE (down-right)
|
||||
},
|
||||
characters: {
|
||||
fallback: isoMale(3),
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
|
||||
// Furniture kinds draw a floor tile as the base + the prop sprite on top (same idea as the
|
||||
// tiled renderer's `over` compositing). Everything else is a plain ground/wall tile.
|
||||
var PROP = { bar: 1, table: 1, chair: 1, keg: 1, shelf: 1, barrel: 1, crate: 1 };
|
||||
var PROP = { bar: 1, table: 1, chair: 1, keg: 1, shelf: 1, barrel: 1, crate: 1, chest: 1 };
|
||||
var items = [], x, y, kind, p;
|
||||
for (y = 0; y < scene.rows; y++) {
|
||||
for (x = 0; x < scene.cols; x++) {
|
||||
|
||||
@@ -251,6 +251,7 @@
|
||||
function projForMode(mode) {
|
||||
if (mode === 'iso') return 'iso';
|
||||
if (mode === '3d') return '3d';
|
||||
if (mode === 'ascii') return null; // ASCII draws glyphs — it consumes no tile pack
|
||||
return 'topdown';
|
||||
}
|
||||
|
||||
@@ -260,7 +261,7 @@
|
||||
if (!packbar || !RK.unlockedPacks) return;
|
||||
packbar.innerHTML = '';
|
||||
var proj = projForMode(currentMode || 'tiles');
|
||||
var packs = RK.unlockedPacks(proj);
|
||||
var packs = proj ? RK.unlockedPacks(proj) : [];
|
||||
if (packs.length < 2) { packbar.classList.add('hidden'); return; }
|
||||
packbar.classList.remove('hidden');
|
||||
var activeId = RK.activePackId(proj);
|
||||
|
||||
@@ -95,7 +95,9 @@ describe('render pack visual resolver', () => {
|
||||
const RK = loadRenderKit();
|
||||
expect(RK.isoAssets.tiles.floor).toContain('planks_S.png');
|
||||
expect(RK.isoAssets.tiles.floor).not.toContain('stone_S.png');
|
||||
expect(RK.isoAssets.tiles.wall).toContain('stoneWallHalf_S.png');
|
||||
expect(RK.isoAssets.tiles.wall).toContain('stoneWall_S.png'); // full wall from the rich set
|
||||
expect(RK.isoAssets.tiles.window).toContain('stoneWallWindow_S.png'); // real iso window now
|
||||
expect(RK.isoAssets.tiles.table).toContain('tableShortChairs_S.png'); // distinct furniture art
|
||||
});
|
||||
|
||||
test('iso pack treats imported Male files as directions, not class variants', () => {
|
||||
@@ -105,11 +107,12 @@ describe('render pack visual resolver', () => {
|
||||
expect(RK.isoAssets.characters['char-merchant']).toBeUndefined();
|
||||
expect(RK.isoAssets.characters['char-wizard']).toBeUndefined();
|
||||
expect(RK.isoAssets.characters['char-goblin']).toBeUndefined();
|
||||
// 45° renders: 0=NW,2=SW,4=SE,6=NE. Facing follows visual movement (up->NE, down->SW, etc.).
|
||||
expect(RK.isoAssets.directions.down.idle).toContain('Male_2_Idle0.png');
|
||||
expect(RK.isoAssets.directions.up.idle).toContain('Male_6_Idle0.png');
|
||||
expect(RK.isoAssets.directions.left.idle).toContain('Male_0_Idle0.png');
|
||||
expect(RK.isoAssets.directions.right.idle).toContain('Male_4_Idle0.png');
|
||||
// Sprites are angled clockwise from NE: 0=NE,2=SE,4=SW,6=NW (verified against live movement).
|
||||
// Facing follows visual movement (up->NE, down->SW, left->NW, right->SE).
|
||||
expect(RK.isoAssets.directions.up.idle).toContain('Male_0_Idle0.png');
|
||||
expect(RK.isoAssets.directions.right.idle).toContain('Male_2_Idle0.png');
|
||||
expect(RK.isoAssets.directions.down.idle).toContain('Male_4_Idle0.png');
|
||||
expect(RK.isoAssets.directions.left.idle).toContain('Male_6_Idle0.png');
|
||||
});
|
||||
|
||||
test('projection visuals expose the saved base tint as a render color', () => {
|
||||
|
||||