-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbatch-sprites.mjs
More file actions
132 lines (116 loc) · 7.39 KB
/
Copy pathbatch-sprites.mjs
File metadata and controls
132 lines (116 loc) · 7.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env node
import { execSync } from 'node:child_process';
import { mkdirSync, existsSync } from 'node:fs';
// --- directories ---
const DIRS = ['sprites/raw', 'sprites/nobg', 'sprites/final', 'sprites/sheets'];
DIRS.forEach(d => mkdirSync(d, { recursive: true }));
// --- helper ---
function run(cmd) {
console.log(`\n$ ${cmd}`);
execSync(cmd, { stdio: 'inherit' });
}
// --- sprite definitions ---
const SPRITES = [
// --- TURNAROUND ---
{
name: 'companion-front',
prompt: 'This exact same character standing relaxed facing directly forward, both hands gripping backpack straps, feet slightly apart, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no ground, no text',
},
{
name: 'companion-side-right',
prompt: 'This exact same character standing in right-facing side view, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no ground, no text',
},
{
name: 'companion-side-left',
prompt: 'This exact same character standing in left-facing side view, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no ground, no text',
},
{
name: 'companion-back',
prompt: 'This exact same character standing facing directly away from the viewer showing her back, backpack fully visible, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no ground, no text',
},
// --- WALK CYCLE (right-facing) ---
{
name: 'walk-01',
prompt: 'This exact same character in right-facing side view, walking pose frame 1 of 4 CONTACT: SHORT compact step, right foot only slightly forward, left foot only slightly back, feet stay close, knees slightly bent, body at lowest point, left arm forward, right arm back, ponytail lagging, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no ground, no text',
},
{
name: 'walk-02',
prompt: 'This exact same character in right-facing side view, walking pose frame 2 of 4 PASSING: SHORT step, right support leg underneath, left foot swinging through just off the ground beside the support ankle (not a high knee), feet stay close, body at highest point, arms mid-swing, ponytail bouncing up, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no ground, no text',
},
{
name: 'walk-03',
prompt: 'This exact same character in right-facing side view, walking pose frame 3 of 4 CONTACT: SHORT compact step, left foot only slightly forward, right foot only slightly back, feet stay close, knees slightly bent, body at lowest point, right arm forward, left arm back, ponytail lagging, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no ground, no text',
},
{
name: 'walk-04',
prompt: 'This exact same character in right-facing side view, walking pose frame 4 of 4 PASSING: SHORT step, left support leg underneath, right foot swinging through just off the ground beside the support ankle (not a high knee), feet stay close, body at highest point, arms mid-swing, ponytail bouncing up, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no ground, no text',
},
// --- ACTIVITY POSES ---
{
name: 'sit-campfire',
prompt: 'This exact same character sitting cross-legged on the ground beside a campfire in right-facing side view, hands stretched toward fire warming them, relaxed happy expression, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no text',
},
{
name: 'roast-marshmallow',
prompt: 'This exact same character sitting cross-legged beside a campfire in right-facing side view, holding a long stick with a marshmallow over flames, cheerful excited expression, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no text',
},
{
name: 'fishing',
prompt: 'This exact same character sitting at the edge of water in right-facing side view, holding a fishing rod with line extending right, legs dangling, peaceful content expression, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no text',
},
{
name: 'reading',
prompt: 'This exact same character sitting cross-legged on the ground in right-facing side view, holding an open book in both hands, looking down at book, calm focused expression, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no text',
},
{
name: 'stargazing',
prompt: 'This exact same character lying on her back on the ground, head to the left, looking up at sky with wonder-filled expression, hands behind head, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no text',
},
{
name: 'sleeping-tent',
prompt: 'This exact same character curled up sleeping inside a small open tent seen from tent opening in side view, eyes closed, peaceful smile, hugging small pillow, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no text',
},
{
name: 'waving',
prompt: 'This exact same character in 3/4 front-facing view, waving cheerfully with right hand raised, big happy grin, left hand on backpack strap, full body, centered, solid magenta (#FF00FF) background, pixel art, crisp hard pixel edges, no anti-aliasing, no shadow, no ground, no text',
},
];
// --- pipeline ---
console.log(`\n=== PIXEL CAMP SPRITE PIPELINE ===`);
console.log(`Sprites to generate: ${SPRITES.length}`);
console.log(`Pipeline: generate → remove bg → downscale to 64px\n`);
for (const sprite of SPRITES) {
const raw = `sprites/raw/${sprite.name}.png`;
const nobg = `sprites/nobg/${sprite.name}.png`;
const final = `sprites/final/${sprite.name}.png`;
// Skip if final already exists
if (existsSync(final)) {
console.log(`\nSkipping ${sprite.name} (already exists)`);
continue;
}
console.log(`\n━━━ ${sprite.name} ━━━`);
// Step 1: Generate with reference
if (!existsSync(raw)) {
const escaped = sprite.prompt.replace(/'/g, "'\\''");
run(`node --env-file=.env scripts/gen-image.mjs --prompt '${escaped}' --out ${raw}`);
}
// Step 2: Remove background
if (!existsSync(nobg)) {
run(`node --env-file=.env scripts/remove-bg.mjs --in ${raw} --out ${nobg}`);
}
// Step 3: Downscale to 64px
run(`node scripts/pixelate.mjs --in ${nobg} --out ${final} --size 64`);
}
// --- assemble walk sheet ---
console.log(`\n━━━ ASSEMBLING SHEETS ━━━`);
const walkFrames = [1, 2, 3, 4]
.map(n => `sprites/final/walk-0${n}.png`)
.filter(f => existsSync(f));
if (walkFrames.length === 4) {
run(`node scripts/make-sheet.mjs --out sprites/sheets/walk-right.png ${walkFrames.join(' ')}`);
} else {
console.log(`Walk sheet skipped (${walkFrames.length}/4 frames ready)`);
}
console.log(`\n=== DONE ===`);
console.log(`Final sprites: sprites/final/`);
console.log(`Sprite sheets: sprites/sheets/`);