105 lines
3.8 KiB
JavaScript
Executable file
105 lines
3.8 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
/**
|
|
* Exportiert Pixel-Sprites pro Stufe + Mood als PNG und Sheets.
|
|
* Nutzung: node scripts/export-sprites.js
|
|
* Braucht: google-chrome + python3/pillow
|
|
*/
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const { execSync, spawnSync } = require('child_process');
|
|
|
|
const ROOT = path.resolve(__dirname, '..');
|
|
const OUT = path.join(ROOT, 'assets', 'sprites');
|
|
const TMP = '/tmp/ck-sprites';
|
|
const STAGES = ['funke','kleiner-kumpel','junior-coder','senior-kumpel','code-meister'];
|
|
const MOODS = ['neugierig','denkend','stolz','verwirrt','müde'];
|
|
const MOOD_FILE = { neugierig:'neugierig', denkend:'denkend', stolz:'stolz', verwirrt:'verwirrt', 'müde':'muede' };
|
|
const SIZE = 128;
|
|
|
|
fs.mkdirSync(TMP, { recursive: true });
|
|
fs.mkdirSync(path.join(OUT, 'sheets'), { recursive: true });
|
|
|
|
const avatarSrc = fs.readFileSync(path.join(ROOT, 'avatar-pixel.js'), 'utf8');
|
|
|
|
const html = `<!doctype html><html><head><meta charset=utf-8>
|
|
<style>
|
|
html,body{margin:0;background:transparent;overflow:hidden}
|
|
#grid{display:flex;flex-wrap:wrap;width:${5*SIZE}px}
|
|
.cell{width:${SIZE}px;height:${SIZE}px;display:flex;align-items:center;justify-content:center}
|
|
svg{width:${SIZE}px;height:${SIZE}px;image-rendering:pixelated}
|
|
</style></head><body>
|
|
<script>${avatarSrc}</script>
|
|
<script>
|
|
const moods=${JSON.stringify(MOODS)};
|
|
const grid=document.createElement('div'); grid.id='grid'; document.body.appendChild(grid);
|
|
for(let st=0;st<5;st++){
|
|
for(const m of moods){
|
|
const cell=document.createElement('div'); cell.className='cell';
|
|
const svg=document.createElementNS('http://www.w3.org/2000/svg','svg');
|
|
svg.setAttribute('viewBox','0 0 200 200');
|
|
svg.innerHTML = buddyPixelSVG(st, m);
|
|
cell.appendChild(svg); grid.appendChild(cell);
|
|
}
|
|
}
|
|
</script></body></html>`;
|
|
|
|
const htmlPath = path.join(TMP, 'sprites.html');
|
|
fs.writeFileSync(htmlPath, html);
|
|
const shotPath = path.join(TMP, 'all.png');
|
|
|
|
console.log('Chrome screenshot…');
|
|
const r = spawnSync('google-chrome', [
|
|
'--headless=new','--disable-gpu','--hide-scrollbars','--no-sandbox',
|
|
'--default-background-color=00000000',
|
|
`--window-size=${5*SIZE},${5*SIZE}`,
|
|
`--screenshot=${shotPath}`,
|
|
'file://'+htmlPath
|
|
], { encoding:'utf8' });
|
|
if (r.status !== 0){ console.error(r.stderr||r.stdout); process.exit(1); }
|
|
if (!fs.existsSync(shotPath)){ console.error('Screenshot missing'); process.exit(1); }
|
|
|
|
const py = `
|
|
from PIL import Image
|
|
import os
|
|
img = Image.open(${JSON.stringify(shotPath)}).convert('RGBA')
|
|
W,H = img.size
|
|
cell = ${SIZE}
|
|
cols, rows = 5, 5
|
|
ow, oh = cols*cell, rows*cell
|
|
if W >= ow and H >= oh:
|
|
sheet = img.crop((0,0,ow,oh))
|
|
else:
|
|
sheet = img.resize((ow,oh), Image.NEAREST)
|
|
stages = ${JSON.stringify(STAGES)}
|
|
moods = ${JSON.stringify(MOODS)}
|
|
mood_file = ${JSON.stringify(MOOD_FILE)}
|
|
out = ${JSON.stringify(OUT)}
|
|
os.makedirs(os.path.join(out,'sheets'), exist_ok=True)
|
|
for st in range(5):
|
|
folder = os.path.join(out, f'stage-{st}-{stages[st]}')
|
|
os.makedirs(folder, exist_ok=True)
|
|
row_imgs = []
|
|
for mi,m in enumerate(moods):
|
|
x,y = mi*cell, st*cell
|
|
tile = sheet.crop((x,y,x+cell,y+cell))
|
|
fn = os.path.join(folder, mood_file[m] + '.png')
|
|
tile.save(fn)
|
|
row_imgs.append(tile)
|
|
print('wrote', fn)
|
|
row = Image.new('RGBA', (cols*cell, cell), (0,0,0,0))
|
|
for i,t in enumerate(row_imgs):
|
|
row.paste(t, (i*cell, 0))
|
|
sp = os.path.join(out,'sheets', f'stage-{st}-sheet.png')
|
|
row.save(sp)
|
|
print('sheet', sp)
|
|
full = Image.new('RGBA', (cols*cell, rows*cell), (0,0,0,0))
|
|
full.paste(sheet, (0,0))
|
|
fp = os.path.join(out,'sheets','all-stages-sheet.png')
|
|
full.save(fp)
|
|
print('full', fp)
|
|
`;
|
|
const pyPath = path.join(TMP, 'slice.py');
|
|
fs.writeFileSync(pyPath, py);
|
|
console.log('Slicing…');
|
|
execSync('python3 '+pyPath, { stdio:'inherit' });
|
|
console.log('OK →', OUT);
|