Files
game-forest/src/game/sprites.ts
T

285 lines
5.8 KiB
TypeScript

/** 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<string, string>): 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,
);