explodorama / commit
Outer wall as a bordered stone frame
PLAN.md | 2 +- assets/kenney/terrain_stone_block_bottom_left.png | Bin 0 -> 1178 bytes assets/kenney/terrain_stone_block_bottom_right.png | Bin 0 -> 1167 bytes assets/kenney/terrain_stone_block_center.png | Bin 920 -> 0 bytes assets/kenney/terrain_stone_block_top_left.png | Bin 0 -> 1320 bytes assets/kenney/terrain_stone_block_top_right.png | Bin 0 -> 1331 bytes assets/kenney/terrain_stone_horizontal_middle.png | Bin 0 -> 978 bytes assets/kenney/terrain_stone_vertical_middle.png | Bin 0 -> 938 bytes decisions.md | 15 +++++++++++++ docs/screenshots/auto-move.png | Bin 249023 -> 249559 bytes docs/screenshots/bomb-picked.png | Bin 248985 -> 249435 bytes docs/screenshots/charges.png | Bin 276870 -> 277032 bytes docs/screenshots/countdown.png | Bin 253578 -> 253982 bytes docs/screenshots/death.png | Bin 198263 -> 199246 bytes docs/screenshots/desktop.png | Bin 593333 -> 598296 bytes docs/screenshots/dev.png | Bin 266198 -> 267516 bytes docs/screenshots/enemies.png | Bin 252627 -> 252762 bytes docs/screenshots/info-enemy.png | Bin 192237 -> 191188 bytes docs/screenshots/info-hud.png | Bin 182314 -> 181634 bytes docs/screenshots/lingering.png | Bin 257820 -> 258424 bytes docs/screenshots/long-press.png | Bin 251937 -> 252346 bytes docs/screenshots/menu.png | Bin 190391 -> 189637 bytes docs/screenshots/new-run.png | Bin 194300 -> 193766 bytes docs/screenshots/pierce-decoy.png | Bin 284653 -> 284698 bytes docs/screenshots/power-up.png | Bin 261831 -> 261868 bytes docs/screenshots/run.png | Bin 237216 -> 239526 bytes docs/screenshots/scrolled.png | Bin 261157 -> 259762 bytes docs/screenshots/small-desktop.png | Bin 279278 -> 280692 bytes docs/screenshots/small.png | Bin 189686 -> 194117 bytes docs/screenshots/start.png | Bin 247835 -> 248312 bytes src/render/board.ts | 18 +++++++++++++++- src/render/sprites.ts | 24 +++++++++++++++++---- src/ui/info.ts | 4 ++-- 33 files changed, 55 insertions(+), 8 deletions(-) diff --git a/PLAN.md b/PLAN.md index 7f7f023..07a5083 100644 --- a/PLAN.md +++ b/PLAN.md @@ -479,7 +479,7 @@ Sprite assignments (✅ = drawn now; the rest are copied and waiting for their f | Thing | Sprite(s) in `assets/kenney/` | |---|---| | ✅ player | `character_green_idle`; `character_green_hit` when dead; mirrored when facing left. Other green frames (walk, jump, duck, climb, front) are there for animation. | -| ✅ outer wall | `terrain_stone_block_center` | +| ✅ outer wall | a bordered stone frame (2026-10-22): `terrain_stone_horizontal_middle` top and bottom, `terrain_stone_vertical_middle` left and right, `terrain_stone_block_top_left` / `_top_right` / `_bottom_left` / `_bottom_right` corners; the four inner corners, which the pack has no piece for, get a small square in the outline colour | | ✅ pillars | `block_blue`, `block_green`, `block_red`, `block_yellow`, cycling by level | | ✅ soft block | `block_planks` (wooden crate) | | ✅ bomb | `bomb`; flashes to `bomb_active` on its last turn; timer drawn in `hud_character_0`–`9` | diff --git a/assets/kenney/terrain_stone_block_bottom_left.png b/assets/kenney/terrain_stone_block_bottom_left.png new file mode 100644 index 0000000..8f5f500 Binary files /dev/null and b/assets/kenney/terrain_stone_block_bottom_left.png differ diff --git a/assets/kenney/terrain_stone_block_bottom_right.png b/assets/kenney/terrain_stone_block_bottom_right.png new file mode 100644 index 0000000..a714beb Binary files /dev/null and b/assets/kenney/terrain_stone_block_bottom_right.png differ diff --git a/assets/kenney/terrain_stone_block_center.png b/assets/kenney/terrain_stone_block_center.png deleted file mode 100644 index 23ef36a..0000000 Binary files a/assets/kenney/terrain_stone_block_center.png and /dev/null differ diff --git a/assets/kenney/terrain_stone_block_top_left.png b/assets/kenney/terrain_stone_block_top_left.png new file mode 100644 index 0000000..1992d2c Binary files /dev/null and b/assets/kenney/terrain_stone_block_top_left.png differ diff --git a/assets/kenney/terrain_stone_block_top_right.png b/assets/kenney/terrain_stone_block_top_right.png new file mode 100644 index 0000000..a609052 Binary files /dev/null and b/assets/kenney/terrain_stone_block_top_right.png differ diff --git a/assets/kenney/terrain_stone_horizontal_middle.png b/assets/kenney/terrain_stone_horizontal_middle.png new file mode 100644 index 0000000..41178b1 Binary files /dev/null and b/assets/kenney/terrain_stone_horizontal_middle.png differ diff --git a/assets/kenney/terrain_stone_vertical_middle.png b/assets/kenney/terrain_stone_vertical_middle.png new file mode 100644 index 0000000..937f1e4 Binary files /dev/null and b/assets/kenney/terrain_stone_vertical_middle.png differ diff --git a/decisions.md b/decisions.md index de8f1ba..b9f0115 100644 --- a/decisions.md +++ b/decisions.md @@ -237,3 +237,18 @@ Made by me: each other (from memory, not verified). Listed as open question 10 in PLAN.md §14. - **Exclusive power-ups** are written up as an idea with its conflicts (PLAN.md §5b), not built. +### 2026-10-22 — The outer wall gets borders + +The user found the walls too uniform and asked for the pack's bordered wall tiles. + +- **The outer wall is a stone frame**: the edge, corner and strip pieces of the pack's + `terrain_stone` set, so a dark outline runs along both sides of the ring (towards the board and + towards the screen edge) with rounded outer corners. Top and bottom strips show the pack's dark + ledge on their upper side, as in the pack. `terrain_stone_block_center` is no longer used and + was removed from `assets/kenney/`. +- **Inner corners are drawn squares**: the pack has no inner-corner piece, so where two sides of + the frame meet the outline would have a gap; a square in the outline colour fills it. +- **Pillars are unchanged**: the coloured blocks already have their own outline. +- **Floors are drawn before walls** (render only): each tile is drawn a hair oversized to hide + seams, and a floor drawn after its neighbouring wall painted over that wall's edge, leaving + thin light lines through the stone. diff --git a/docs/screenshots/auto-move.png b/docs/screenshots/auto-move.png index ce373cf..8ce407a 100644 Binary files a/docs/screenshots/auto-move.png and b/docs/screenshots/auto-move.png differ diff --git a/docs/screenshots/bomb-picked.png b/docs/screenshots/bomb-picked.png index 2781573..496cb17 100644 Binary files a/docs/screenshots/bomb-picked.png and b/docs/screenshots/bomb-picked.png differ diff --git a/docs/screenshots/charges.png b/docs/screenshots/charges.png index 70222b6..4ed832f 100644 Binary files a/docs/screenshots/charges.png and b/docs/screenshots/charges.png differ diff --git a/docs/screenshots/countdown.png b/docs/screenshots/countdown.png index 06b899d..c6ec468 100644 Binary files a/docs/screenshots/countdown.png and b/docs/screenshots/countdown.png differ diff --git a/docs/screenshots/death.png b/docs/screenshots/death.png index 44fc872..ce02f25 100644 Binary files a/docs/screenshots/death.png and b/docs/screenshots/death.png differ diff --git a/docs/screenshots/desktop.png b/docs/screenshots/desktop.png index 47affca..c226b4c 100644 Binary files a/docs/screenshots/desktop.png and b/docs/screenshots/desktop.png differ diff --git a/docs/screenshots/dev.png b/docs/screenshots/dev.png index d6007a1..2eb22cf 100644 Binary files a/docs/screenshots/dev.png and b/docs/screenshots/dev.png differ diff --git a/docs/screenshots/enemies.png b/docs/screenshots/enemies.png index 74e9193..c2b3abb 100644 Binary files a/docs/screenshots/enemies.png and b/docs/screenshots/enemies.png differ diff --git a/docs/screenshots/info-enemy.png b/docs/screenshots/info-enemy.png index 7b18125..edf0b8a 100644 Binary files a/docs/screenshots/info-enemy.png and b/docs/screenshots/info-enemy.png differ diff --git a/docs/screenshots/info-hud.png b/docs/screenshots/info-hud.png index 189e32c..f8fff59 100644 Binary files a/docs/screenshots/info-hud.png and b/docs/screenshots/info-hud.png differ diff --git a/docs/screenshots/lingering.png b/docs/screenshots/lingering.png index 1ca8059..c13fb65 100644 Binary files a/docs/screenshots/lingering.png and b/docs/screenshots/lingering.png differ diff --git a/docs/screenshots/long-press.png b/docs/screenshots/long-press.png index dd650c1..9c838db 100644 Binary files a/docs/screenshots/long-press.png and b/docs/screenshots/long-press.png differ diff --git a/docs/screenshots/menu.png b/docs/screenshots/menu.png index fbf0b1d..1c26558 100644 Binary files a/docs/screenshots/menu.png and b/docs/screenshots/menu.png differ diff --git a/docs/screenshots/new-run.png b/docs/screenshots/new-run.png index 4b25e7b..68ada1b 100644 Binary files a/docs/screenshots/new-run.png and b/docs/screenshots/new-run.png differ diff --git a/docs/screenshots/pierce-decoy.png b/docs/screenshots/pierce-decoy.png index 3103de5..05879da 100644 Binary files a/docs/screenshots/pierce-decoy.png and b/docs/screenshots/pierce-decoy.png differ diff --git a/docs/screenshots/power-up.png b/docs/screenshots/power-up.png index 538df8c..de6ca69 100644 Binary files a/docs/screenshots/power-up.png and b/docs/screenshots/power-up.png differ diff --git a/docs/screenshots/run.png b/docs/screenshots/run.png index b48073b..c7a8277 100644 Binary files a/docs/screenshots/run.png and b/docs/screenshots/run.png differ diff --git a/docs/screenshots/scrolled.png b/docs/screenshots/scrolled.png index 5df6f6d..aa02540 100644 Binary files a/docs/screenshots/scrolled.png and b/docs/screenshots/scrolled.png differ diff --git a/docs/screenshots/small-desktop.png b/docs/screenshots/small-desktop.png index 1ea247b..d290ee0 100644 Binary files a/docs/screenshots/small-desktop.png and b/docs/screenshots/small-desktop.png differ diff --git a/docs/screenshots/small.png b/docs/screenshots/small.png index 90c6a19..526d025 100644 Binary files a/docs/screenshots/small.png and b/docs/screenshots/small.png differ diff --git a/docs/screenshots/start.png b/docs/screenshots/start.png index 7473295..0e08f97 100644 Binary files a/docs/screenshots/start.png and b/docs/screenshots/start.png differ diff --git a/src/render/board.ts b/src/render/board.ts index dff6db7..b35da5d 100644 --- a/src/render/board.ts +++ b/src/render/board.ts @@ -84,8 +84,12 @@ const C = { powerUpGlow: rgb(1, 0.95, 0.55, 0.8), star: rgb(1, 0.85, 0.2, 0.9), blocked: rgb(0.85, 0.2, 0.2, 0.35), + stoneOutline: rgb(53 / 255, 53 / 255, 65 / 255), } +/** The stone frame's outline: 8 of its sprites' 128 pixels. */ +const STONE_OUTLINE = 8 / 128 + export const BACKGROUND: Color = C.sky @@ -96,12 +100,15 @@ export function drawBoard(view: View): void { const tileSize = vec2(1) const crumbling = new Map(s.crumbling.map((c) => [c.cell, c.turns])) + // Floors first: drawn a hair oversized too, a later one would paint over the last wall's edge. + for (let y = 0; y < s.height; y++) { + for (let x = 0; x < s.width; x++) drawRect(toWorld(s, { x, y }), wallSize, (x + y) % 2 ? C.floorAlt : C.floor) + } for (let y = 0; y < s.height; y++) { for (let x = 0; x < s.width; x++) { const p = { x, y } const pos = toWorld(s, p) const cell = s.cells[idx(s, p)] - drawRect(pos, wallSize, (x + y) % 2 ? C.floorAlt : C.floor) if (cell === 'wall') drawTile(pos, wallSize, sprite(wallSprite(s.level, s.width, s.height, p))) else if (cell === 'block') { // A crumbling crate shakes, harder and fainter the closer it is to gone. @@ -114,6 +121,15 @@ export function drawBoard(view: View): void { } } } + // The stone frame has no inner-corner piece, so its outline gets a square where the sides meet, + // lined up with the oversized wall sprites' outline. + const outline = wallSize.x * STONE_OUTLINE + const reach = 0.5 - (wallSize.x - 1) / 2 + outline / 2 + for (const [x, dx] of [[1, -1], [s.width - 2, 1]] as const) { + for (const [y, dy] of [[1, 1], [s.height - 2, -1]] as const) { + drawRect(toWorld(s, { x, y }).add(vec2(dx * reach, dy * reach)), vec2(outline), C.stoneOutline) + } + } if (cellAt(s, s.exit) === 'floor') drawExit(toWorld(s, s.exit), exitOpen(s)) // The level's power-up, once its crate is gone: on a soft glow, so it stands out from drops. if (s.powerUp && cellAt(s, s.powerUp.pos) === 'floor') { diff --git a/src/render/sprites.ts b/src/render/sprites.ts index bf43d52..b2e8a1d 100644 --- a/src/render/sprites.ts +++ b/src/render/sprites.ts @@ -16,7 +16,12 @@ export function spriteUrl(name: string): string { /** The sprites drawn on the canvas. Their order is their LittleJS texture index. */ const BOARD = [ - 'terrain_stone_block_center', + 'terrain_stone_horizontal_middle', + 'terrain_stone_vertical_middle', + 'terrain_stone_block_top_left', + 'terrain_stone_block_top_right', + 'terrain_stone_block_bottom_left', + 'terrain_stone_block_bottom_right', 'block_blue', 'block_green', 'block_red', @@ -104,10 +109,21 @@ export function digitSprite(d: number): TileInfo { /** Pillars change colour from level to level; the outer wall is always stone. */ const PILLARS: BoardSprite[] = ['block_blue', 'block_green', 'block_red', 'block_yellow'] -/** The sprite of a wall tile: stone on the level's edge, otherwise the level's pillar colour. */ +export function isOuterWall(width: number, height: number, p: { x: number; y: number }): boolean { + return p.x === 0 || p.y === 0 || p.x === width - 1 || p.y === height - 1 +} + +/** + * The sprite of a wall tile: the level's pillar colour inside; on the edge, the piece of a stone + * frame whose dark outline runs along both sides of the ring, with rounded outer corners. + */ export function wallSprite(level: number, width: number, height: number, p: { x: number; y: number }): BoardSprite { - const edge = p.x === 0 || p.y === 0 || p.x === width - 1 || p.y === height - 1 - return edge ? 'terrain_stone_block_center' : PILLARS[(level - 1) % PILLARS.length]! + if (!isOuterWall(width, height, p)) return PILLARS[(level - 1) % PILLARS.length]! + const top = p.y === 0 + const bottom = p.y === height - 1 + if (p.x === 0 && (top || bottom)) return top ? 'terrain_stone_block_top_left' : 'terrain_stone_block_bottom_left' + if (p.x === width - 1 && (top || bottom)) return top ? 'terrain_stone_block_top_right' : 'terrain_stone_block_bottom_right' + return top || bottom ? 'terrain_stone_horizontal_middle' : 'terrain_stone_vertical_middle' } /** The icon for each action charge, on the board (as a drop) and on its button. */ diff --git a/src/ui/info.ts b/src/ui/info.ts index 34a7044..ca6b3e2 100644 --- a/src/ui/info.ts +++ b/src/ui/info.ts @@ -4,7 +4,7 @@ import { bombAt, cellAt, eq, exitOpen, isBurning, PAR_BONUS } from '../sim/state import { COIN_BAG, EXIT_SPAWN, STAR_TURNS } from '../sim/turn' import type { ChargeId, Dir, EnemyKind, GameState, Powers, PowerUpKind, Vec } from '../sim/types' import { dirBetween } from '../sim/enemies' -import { CHARGE_ICONS, coinSprite, ENEMY_SPRITES, POWER_UP_ICONS, spriteUrl, wallSprite } from '../render/sprites' +import { CHARGE_ICONS, coinSprite, ENEMY_SPRITES, isOuterWall, POWER_UP_ICONS, spriteUrl, wallSprite } from '../render/sprites' /** * What the game says about each thing on the board and in the top bar, for the info dialog @@ -183,7 +183,7 @@ export function tileInfo(s: GameState, p: Vec): Info | null { const cell = cellAt(s, p) if (cell === 'wall') { const icon = wallSprite(s.level, s.width, s.height, p) - const pillar = icon !== 'terrain_stone_block_center' + const pillar = !isOuterWall(s.width, s.height, p) return { icon, title: pillar ? 'Pillar' : 'Outer wall',