diff --git a/html/js/render/catSprites.js b/html/js/render/catSprites.js
index a7b2b39..d49304b 100644
--- a/html/js/render/catSprites.js
+++ b/html/js/render/catSprites.js
@@ -27,9 +27,11 @@
if (!im.complete || !im.naturalWidth) return false;
var frame = Math.floor((now || 0) / FRAME_MS) % FRAMES;
var sx = frame * FW;
- var size = cell * 1.25; // a touch bigger than a tile
+ // The cat occupies only ~40% of its 50x50 frame (lots of transparent padding), so scale
+ // the frame to ~2x the cell and centre it — the visible cat then reads about tile-sized.
+ var size = cell * 2.0;
var dx = e.x * cell + (cell - size) / 2;
- var dy = e.y * cell + cell - size + cell * 0.12;
+ var dy = e.y * cell + (cell - size) / 2 + cell * 0.2; // centred, nudged down onto the tile
ctx.save();
ctx.imageSmoothingEnabled = false;
if (e.facing === 'left') {
diff --git a/html/js/render/sceneModel.js b/html/js/render/sceneModel.js
index af0eee6..56f814a 100644
--- a/html/js/render/sceneModel.js
+++ b/html/js/render/sceneModel.js
@@ -7,19 +7,22 @@
'use strict';
// Tile kinds and how each renderer treats them (glyph for ASCII, colour for tiled/fancy).
+ // `over` names the ground tile an object sits on, so the renderer composites the object over it
+ // (its transparent areas show the floor/wall, not the dark canvas). Ground tiles (wall/floor/rug)
+ // have no `over` — they fill the cell.
var TAVERN_LEGEND = {
wall: { char: '#', color: '#3a3f4b', solid: true },
- window: { char: 'W', color: '#4a6a8a', solid: true },
+ window: { char: 'W', color: '#4a6a8a', solid: true, over: 'wall' },
floor: { char: '·', color: '#6b4d33', solid: false }, // warm wood, not the old dark green
- rug: { char: '=', color: '#7a3b39', solid: false },
- bar: { char: '=', color: '#6a4a2a', solid: true },
- keg: { char: 'k', color: '#5a4028', solid: true },
- shelf: { char: 'h', color: '#4a3a28', solid: true },
- table: { char: 'T', color: '#6a4a2a', solid: true },
- chair: { char: 'c', color: '#5a4028', solid: false }, // walkable — stand on it to "sit"
- barrel: { char: 'B', color: '#5a4028', solid: true },
- crate: { char: 'C', color: '#7a5a38', solid: true },
- door: { char: 'D', color: '#3fb950', solid: false }
+ rug: { char: 'r', color: '#7a3b39', solid: false, over: 'floor' },
+ bar: { char: '=', color: '#6a4a2a', solid: true, over: 'floor' },
+ keg: { char: 'k', color: '#5a4028', solid: true, over: 'floor' },
+ shelf: { char: 'h', color: '#4a3a28', solid: true, over: 'floor' },
+ table: { char: 'T', color: '#6a4a2a', solid: true, over: 'floor' },
+ chair: { char: 'c', color: '#5a4028', solid: false, over: 'floor' }, // walkable — stand on it to "sit"
+ barrel: { char: 'B', color: '#5a4028', solid: true, over: 'floor' },
+ crate: { char: 'C', color: '#7a5a38', solid: true, over: 'floor' },
+ door: { char: 'D', color: '#3fb950', solid: false, over: 'floor' }
};
// Layout character -> tile kind.
diff --git a/html/js/render/tileRenderer.js b/html/js/render/tileRenderer.js
index bf5f78b..a1398d9 100644
--- a/html/js/render/tileRenderer.js
+++ b/html/js/render/tileRenderer.js
@@ -107,9 +107,18 @@
var def = scene.legend[kind] || { color: '#333' };
var coord = useAtlas ? pickVariant(tmap[kind], x, y) : null;
if (coord) {
+ // Object tiles (furniture, windows, torches, treasure…) are transparent
+ // around the object. Legend `over` names the ground they sit on (floor/wall);
+ // draw that first so the transparency shows the room, not the dark canvas.
+ // Pipeline-level: any scene can declare it, not a tavern one-off.
+ if (def.over && tmap[def.over]) {
+ var base = pickVariant(tmap[def.over], x, y);
+ if (base) atlas.draw(ctx, base[0], base[1], px, py, cell);
+ }
atlas.draw(ctx, coord[0], coord[1], px, py, cell);
- // Dark bottom-edge strip grounds a solid wall against the floor below.
- if (def.solid) {
+ // Dark bottom-edge strip grounds a solid WALL against the floor below (not
+ // objects, which already sit on their own base tile).
+ if (def.solid && !def.over) {
var strip = Math.max(2, cell * 0.16);
var sg = ctx.createLinearGradient(0, py + cell - strip, 0, py + cell);
sg.addColorStop(0, 'rgba(0,0,0,0)');
@@ -121,6 +130,10 @@
continue;
}
// Flat-colour fallback for any unmapped kind (or atlas not yet loaded).
+ if (def.over && scene.legend[def.over]) {
+ ctx.fillStyle = scene.legend[def.over].color; // base colour under the object
+ ctx.fillRect(px, py, cell, cell);
+ }
ctx.fillStyle = def.color;
ctx.fillRect(px, py, cell, cell);
ctx.strokeStyle = 'rgba(0,0,0,0.25)';