Files
scrabble-game/assets/vk/cover
Ilia Denisov 70b88c567f feat(vk): move the tile letter to the corner, add the light cover
Sets the letter in the tile's top-left corner with the value staying bottom
right — the in-game tile layout — instead of centring it. The glyph is placed
by its ink box rather than the text origin, so every letter lands on the same
corner whatever its side bearings and ascent.

Adds day-spot: the same crop and camera as night-spot on a light ground, so the
chosen composition exists as a light/dark pair.
2026-07-27 15:46:58 +02:00
..

VK community cover

The cover art for the VK community (1920×768). The community avatar — the «Э» tile — is uploaded separately; this is only the backdrop behind it.

build-cover.mjs is the whole thing: a small software renderer that draws an Эрудит board in perspective with the opening ГРАМОТНОСТЬ / СОПЕРНИК / ЭРУДИЦИЯ / УМ already played, and emits one PNG per art-direction variant plus a contact sheet.

cd assets/vk/cover
node build-cover.mjs                # every variant -> preview/
node build-cover.mjs night-spot     # one variant
FAST=1  node build-cover.mjs        # 1x instead of 2x supersampling, for quick iteration
ZONES=1 node build-cover.mjs        # overlay the VK keep-outs on the render
LAYOUT=cross node build-cover.mjs   # the alternative word arrangement

It needs no install: skia-canvas comes from the render sidecar's node_modules, and the letters are set in Spectral-Bold.ttf from the icon brand folder.

The position

ГРАМОТНОСТЬ opens through the centre square (its Т on H8) and the other three words hook onto a shared letter. assertLegal re-reads the finished grid and fails the build if the centre is uncovered, if a declared word is missing, or if any maximal run of two or more letters is a word nobody played — so the board on the cover is always a position the engine would accept. All four words are in the Эрудит dictionary; tile values come from scrabble-solver rules.Erudit().

The default ladder arrangement puts both long words horizontally. The cross arrangement hangs ЭРУДИЦИЯ down the left instead, which looks more symmetric but collides with the VK mobile avatar (below).

VK keep-outs

Measured off VK's own template (../VK_group_cover_template.fig), in cover pixels:

Zone Area Why
Top crop y < 130 trimmed by some clients — nothing important there
Mobile avatar circle, centre (283, 818), r 283 the community picture sits over the bottom-left in the VK app

ZONES=1 paints both so a composition can be checked against them.

Rendering technique

The camera has pitch only — no roll, no yaw — so a board-space horizontal line always maps to a screen-space horizontal line. That makes the perspective warp an exact per-scanline remap of a flat texture rather than a general homography: the board surface and the tile faces are each drawn once, flat, at high resolution, then replayed band by band (warpPlane). Tile thickness is filled as real 3D quads between the two planes, so the tiles have visible edges.

Two things that are easy to get wrong here and cost a hundredfold in render time: ctx.filter = 'blur(...)' applies per drawing call, so many blurred shapes must be collected into one offscreen layer and blurred once (blurred); and drawImage re-snapshots a live Canvas source on every call, so a texture sampled hundreds of times must be baked into an Image first (freeze).