Board artwork: one component draws the game, the hall's still, and the share card, with gradients on the pieces, plank joins and inlaid corners on the oak, and the stone as it was

npm run art renders the standalone SVGs and the 1200 by 630 card through
Sharp, a development dependency only.
This commit is contained in:
Eric Wagoner
2026-09-23 19:32:15 -04:00
parent 145667ea0d
commit a213a238d3
12 changed files with 1089 additions and 382 deletions
+4 -29
View File
@@ -11,7 +11,8 @@
import { unreadTalk } from '$lib/net/talk';
import type { RoomView } from '$lib/net/view';
import type { State } from '$lib/game';
import { game } from '$lib/game';
import { game, createGame } from '$lib/game';
import BoardArtwork from './BoardArtwork.svelte';
let name = $state(playerName());
let code = $state('');
@@ -22,15 +23,7 @@
);
let prefsOpen = $state(false);
/** The hall's still of the opening position, on whichever board the selector names. */
const still = $derived(
options.set === 'tablut'
? { n: 9, wood: '#8d8577', line: 'rgba(40,34,28,0.5)', dark: '#3d3530', darkRim: '#1c1714', pale: '#cfc4ad', paleRim: '#8c8069', king: '#c9b27a', kingRim: '#7d6636', corners: false,
a: [[3,0],[4,0],[5,0],[4,1],[0,3],[8,3],[0,4],[1,4],[7,4],[8,4],[0,5],[8,5],[4,7],[3,8],[4,8],[5,8]], d: [[4,2],[4,3],[2,4],[3,4],[5,4],[6,4],[4,5],[4,6]] }
: { n: 11, wood: '#8a5a2b', line: 'rgba(30,16,6,0.5)', dark: '#2a2320', darkRim: '#0d0a08', pale: '#ece4d0', paleRim: '#b9ab8b', king: '#f0d58a', kingRim: '#a67c1a', corners: true,
a: [[3,0],[4,0],[5,0],[6,0],[7,0],[5,1],[0,3],[10,3],[0,4],[10,4],[0,5],[1,5],[9,5],[10,5],[0,6],[10,6],[0,7],[10,7],[5,9],[3,10],[4,10],[5,10],[6,10],[7,10]], d: [[5,3],[4,4],[5,4],[6,4],[3,5],[4,5],[6,5],[7,5],[4,6],[5,6],[6,6],[5,7]] }
);
const mid = $derived((still.n - 1) / 2);
const opening = $derived(createGame({ preview: 'Defenders', opponent: 'Attackers' }, 0, undefined, options));
let busy = $state(false);
let error = $state('');
let seats = $state(allSeats());
@@ -217,21 +210,7 @@
</div>
<div class="lid-look" aria-hidden="true">
<svg class="still" class:worn={options.set === 'tablut'} viewBox="0 0 {still.n * 10} {still.n * 10}" aria-hidden="true">
<rect x="0" y="0" width={still.n * 10} height={still.n * 10} rx="4" fill={still.wood} />
{#each Array.from({ length: still.n }, (_, r) => r) as r (r)}
{#each Array.from({ length: still.n }, (_, c) => c) as c (c)}
<rect x={c * 10} y={r * 10} width="10" height="10" fill={still.corners && (r === 0 || r === still.n - 1) && (c === 0 || c === still.n - 1) ? 'rgba(224,101,92,0.4)' : r === mid && c === mid ? 'rgba(240,165,58,0.4)' : 'rgba(255,240,210,0.08)'} stroke={still.line} stroke-width="0.4" />
{/each}
{/each}
{#each still.a as [x, y] (`${x},${y}`)}
<circle cx={x * 10 + 5} cy={y * 10 + 5} r="3.4" fill={still.dark} stroke={still.darkRim} stroke-width="0.6" />
{/each}
{#each still.d as [x, y] (`${x},${y}`)}
<circle cx={x * 10 + 5} cy={y * 10 + 5} r="3.4" fill={still.pale} stroke={still.paleRim} stroke-width="0.6" />
{/each}
<circle cx={mid * 10 + 5} cy={mid * 10 + 5} r="3.6" fill={still.king} stroke={still.kingRim} stroke-width="0.6" />
</svg>
<div class="still"><BoardArtwork g={opening} decorative /></div>
</div>
{#if seats.length}
@@ -641,12 +620,8 @@
display: block;
margin: 0 auto;
border-radius: 4px;
transition: filter 0.9s ease;
}
.still.worn {
filter: contrast(0.85) sepia(0.15);
}
.tally {
display: grid;
grid-template-columns: max-content 1fr;