/** Pixel grids for 8-bit-style sprites. Each cell is a CSS color, or '' for transparent. */ export type PixelGrid = string[][]; function grid(rows: string[], palette: Record): PixelGrid { return rows.map((row) => [...row].map((ch) => palette[ch] ?? '')); } const CHARACTER_PALETTE = { O: '#1b1611', H: '#4a2f1c', S: '#f0c090', s: '#d9a873', B: '#3f6fb0', b: '#2f5488', P: '#2c2c3e', p: '#20202e', F: '#2a1f14', }; export const CHARACTER_SPRITE: PixelGrid = grid( [ '....OOOOOOOO....', '..OHHHHHHHHHHO..', '.OHHHHHHHHHHHHO.', 'OHHHHHHHHHHHHHHO', 'OHHSSSSSSSSSSHHO', 'OSSSSOSSSSOSSSSO', 'OSSSSSSssSSSSSSO', '.OSSSSSSSSSSSSO.', '......OSSO......', '...OBBBBBBBBO...', '..OBBBBBBBBBBO..', '.OSBBBBBBBBBBSO.', '.OSBBbBBBBbBBSO.', '.OSBBbBBBBbBBSO.', '..OBBbBBBBbBBO..', '..OPPpPPPPpPPO..', '..OPPpPPPPpPPO..', '..OPPpO..OpPPO..', '..OPPpO..OpPPO..', '..OPPpO..OpPPO..', '..OFFFO..OFFFO..', '.OFFFFO..OFFFFO.', ], CHARACTER_PALETTE, ); const TREE_PALETTE = { O: '#14290f', G: '#2e7d32', g: '#1b5e20', H: '#66bb6a', T: '#6b4226', t: '#4e2f1a', n: '#8a5a34', }; export const TREE_SPRITE: PixelGrid = grid( [ '......OggO......', '....OGGggGGO....', '..OGGGGggGGGGO..', '.OGgGGGHHGGGgGO.', 'OGgGGGGHHGGGGgGO', 'OGGgGGGggGGGgGGO', 'OGgGGGgGGgGGGgGO', 'OGGgGGGGGGGGgGGO', 'OGgGGGGggGGGGgGO', '.OGgGGGggGGGgGO.', '..OGgGGggGGgGO..', '...OGgGggGgGO...', '....OGgGGgGO....', '......OggO......', '......OTTO......', '......TTTT......', '......TttT......', '......tnnt......', '......TTTT......', '......TOOT......', ], TREE_PALETTE, ); const BUSH_PALETTE = { O: '#1b3312', G: '#5a9c3e', g: '#3f7a2a', H: '#a3d977', }; // Same canopy shape as the tree's foliage (minus its trunk), just recolored and rendered // smaller — a bush is basically a squat tree. export const BUSH_SPRITE: PixelGrid = grid( [ '......OggO......', '....OGGggGGO....', '..OGGGGggGGGGO..', '.OGgGGGHHGGGgGO.', 'OGgGGGGHHGGGGgGO', 'OGGgGGGggGGGgGGO', 'OGgGGGgGGgGGGgGO', 'OGGgGGGGGGGGgGGO', 'OGgGGGGggGGGGgGO', '.OGgGGGggGGGgGO.', '..OGgGGggGGgGO..', '...OGgGggGgGO...', '....OGgGGgGO....', '......OggO......', ], BUSH_PALETTE, ); const LOG_PALETTE = { O: '#2a1a0d', B: '#7a4a2b', C: '#a9703f', // Lighter sunlit top and darker shaded underside give the log roundness instead of a flat // plank look; scattered flecks break up the grain into rough bark texture; the knot (a // branch scar) and the cut end's growth rings both read as a real piece of wood. H: '#c9915a', S: '#5c3820', F: '#3d2818', K: '#241505', R: '#8a5a34', D: '#150c04', W: '#e8c99a', }; export const LOG_SPRITE: PixelGrid = grid( [ '.OOOOOOOOOOOOOOOOOO.', 'OHHHHHHHHHHHHHHHOOHO', 'OHHFHHHHHHHHHHHOCCOO', 'OCCCCKKKCCCCCCOCWWOO', 'OBFBKRRRKFBBBBOWCWCO', 'OCCCKRDRKCCCCCOWWCCO', 'OBBBKRRRKBBBBBOWDCCO', 'OCCCCKKKCCCCCCOWCWCO', 'OBBFBBBBBBFBBBOCWWOO', 'OSSSSSFSSSSSSSSOCCOO', 'OSSSSSSSSSSSSSSSOOSO', '.OOOOOOOOOOOOOOOOOO.', ], LOG_PALETTE, ); const TWIG_PALETTE = { O: '#241708', T: '#8a5a34', L: '#5a9c3e', }; // A forked twig: a zigzagging main stem (it bends partway up, like a real snapped branch) with a // shorter side-fork breaking off it and a small leaf bud at the tip. export const TWIG_SPRITE: PixelGrid = grid( [ '..........LL...', '..........OTL..', '.........OTO...', '........OTO....', '.......OTO.....', '.OT...OTO......', '..OT.OTO.......', '...OTOTO.......', '....OTO........', '....OTO........', '...OTO.........', '..OTO..........', '.OTO...........', 'OTO............', ], TWIG_PALETTE, ); const COIN_PALETTE = { Y: '#f5c518', D: '#c99a0e', W: '#fff2b0', E: '#a97c08', }; export const COIN_SPRITE: PixelGrid = grid( [ '.....YYYYYY.....', '...YYYYYYYYYY...', '..YWWYYYYYYYYY..', '.YYWWYYYYYYYYYY.', '.YYYYYYYYYYYYYY.', 'YYYYYDDDDDDYYYYY', 'YYYYYDYYYYDYYYYY', 'YYYYYDYYYYDYYYYY', 'YYYYYDYYYYDYYYYY', 'YYYYYDYYYYDYYYYY', 'YYYYYDDDDDDYYYYY', '.YYYYYYYYYYYYYY.', '.YYYYYYYYYYEEYY.', '..YYYYYYYYYEEY..', '...YYYYYYYYYY...', '.....YYYYYY.....', ], COIN_PALETTE, ); const RABBIT_ROWS = [ '...OFO..OFO...', '...OPO..OPO...', '...OPO..OPO...', '...OPO..OPO...', '...OFOOOOFO...', '...OFFFFFFO...', '..FFFFFFFFFF..', '.OFFEFFFFEFFO.', 'OFFFFFNNFFFFFO', 'OFFFFFFFFFFFFO', 'OffffffffffffO', '.OffffffffffO.', '..ffffffffff..', '...OffffffO...', ]; const RABBIT_PALETTE = { O: '#2a1f1a', F: '#e8e0d0', f: '#c9bfa8', P: '#f0a8b0', E: '#1b1611', N: '#d97a86', }; export const RABBIT_SPRITE: PixelGrid = grid(RABBIT_ROWS, RABBIT_PALETTE); // Same shape, recolored — rabbits turn red and hunt the character at night (see GameStore). const RABBIT_NIGHT_PALETTE = { O: '#3a0e0e', F: '#c94040', f: '#8f2222', P: '#f0a8b0', E: '#0d0505', N: '#3a0e0e', }; export const RABBIT_NIGHT_SPRITE: PixelGrid = grid(RABBIT_ROWS, RABBIT_NIGHT_PALETTE); const MEAT_PALETTE = { O: '#4a1414', R: '#c0392b', r: '#8e2a20', W: '#f0e0d0', }; export const MEAT_SPRITE: PixelGrid = grid( [ '..............', '....OOOOO.....', '..ORRRRRRRO...', '.ORRWWRRRRRO..', '.RRRRWWRRRRR..', 'ORRRRRRRRWRRO.', 'ORRRRRRRRWWRO.', 'OrrrrrrrrrrrO.', '.rrrrrrrrrrr..', '.OrrrrrrrrrO..', '..OrrrrrrrO...', '....OOOOO.....', ], MEAT_PALETTE, ); const HEART_PALETTE = { O: '#5a0f0f', F: '#e0333f', }; export const HEART_SPRITE: PixelGrid = grid( [ '.OO..OO.', 'OFFOOFFO', 'OFFFFFFO', '.OFFFFO.', '..OFFO..', '...OO...', ], HEART_PALETTE, );