sandoniette/scripts/gen-assets.sh
type-two 802f738a3d M0: vite+ts+phaser+Matter skeleton, harness, box drops flush
- Phaser 3.90 Matter, autoUpdate:false — deterministic stepSim(dt), harness-driven.
- Render contract: raw Matter body = truth, flat black silhouette follows.
- Rng (mulberry32) ported from toastsim; dev harness on window.__s.
- Exit-bar measured: box drops y=80 -> settles 68 frames -> rests y=608.05,
  gap -0.05px flush on floor, landed:true. Verified in-browser + screenshot.
- scripts/gen-assets.sh (2D-only flux via MODELBEAST) firing in background.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 20:02:27 +10:00

88 lines
4.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# SANDONIETTE asset generation — 2D ONLY, 100% local/free, via MODELBEAST.
# ./scripts/gen-assets.sh # generate all missing 2D assets
# Seeds fixed so every asset is re-generatable. Style token shared for coherence.
# The game NEVER blocks on these — procedural fallbacks cover every prop.
set -uo pipefail
MB_DIR="$HOME/MODELBEAST"
[ -d "$MB_DIR" ] || MB_DIR="$HOME/Documents/MODELBEAST"
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
OUT_IMG="$REPO/public/assets/img"
mkdir -p "$OUT_IMG"
cd "$MB_DIR" || exit 1
# shellcheck disable=SC1091
if [ -f data/agent.env ]; then source data/agent.env
else set -a; source "$HOME/Documents/backnforth/.env"; set +a; fi
export MB_HOST="${MB_HOST:-http://100.89.131.57:8777}"
STYLE="japanese shadow puppet theatre, flat black silhouette with cut-out details, warm washi paper backdrop, edo period, high contrast, hand-crafted paper texture"
# ponytail: m4pro venvs dead (2026-07-17) — jobs there fail in ~1s, so retry up
# to 10x with 60s pauses until a healthy node takes it. Drop once m4pro is fixed.
MB_TRIES=10 MB_PAUSE=60
run_flux() {
local seed="$1" prompt="$2" w="${3:-1024}" h="${4:-1024}" i out
for i in $(seq 1 "$MB_TRIES"); do
out=$(./mb run flux_local -p prompt="$prompt" -p model=flux2-klein-4b -p steps=4 \
-p seed="$seed" -p width="$w" -p height="$h" --wait 2>/dev/null \
| awk '/image/{print $1}' | tail -1)
[ -n "$out" ] && { echo "$out"; return; }
sleep "$MB_PAUSE"
done
}
run_cutout() {
local asset="$1" i out
for i in $(seq 1 "$MB_TRIES"); do
out=$(./mb run bg_remove_local --asset "$asset" -p resolution=2048 --wait 2>/dev/null \
| awk '/image/{print $1}' | tail -1)
[ -n "$out" ] && { echo "$out"; return; }
sleep "$MB_PAUSE"
done
}
# gen_2d <name> <seed> <prompt> [w] [h] [cut]
gen_2d() {
local name="$1" seed="$2" prompt="$3" w="${4:-1024}" h="${5:-1024}" cutout="${6:-no}"
if [ -f "$OUT_IMG/$name.png" ]; then echo " = $name.png exists, skipping"; return; fi
echo "→ [$name] flux..."
local img; img=$(run_flux "$seed" "$prompt, $STYLE" "$w" "$h")
[ -z "$img" ] && { echo " ! $name: flux failed"; return 1; }
if [ "$cutout" = "cut" ]; then
echo "→ [$name] cutout..."
local c; c=$(run_cutout "$img"); [ -n "$c" ] && img="$c"
fi
local tmp; tmp=$(mktemp -d)
./mb get "$img" -o "$tmp" >/dev/null 2>&1
local f; f=$(find "$tmp" -iname '*.png' -o -iname '*.jpg' | head -1)
[ -n "$f" ] && { mv "$f" "$OUT_IMG/$name.png"; echo "$name.png"; }
rm -rf "$tmp"
}
# ---- the samurai: SAME seed, only the expression phrase varies (judge-portrait trick) ----
SAMURAI="a seated japanese samurai looming over a kitchen, ornate armor and helmet, one hand near a katana at his hip, shown as a dramatic flat black paper-cut silhouette against a warm glowing washi paper screen"
gen_2d bg_washi 301 "empty kitchen stage, shoji paper screen backdrop lit warm from behind, wooden theatre framing, no characters, no text" 1280 768
gen_2d floor_boards 303 "seamless dark wooden stage floor boards texture, worn edo-period timber, flat even light, no objects, no text" 1024 512
gen_2d samurai_calm 320 "$SAMURAI, calm neutral expression, katana fully sheathed" 768 900 cut
gen_2d samurai_watch 320 "$SAMURAI, one eyebrow raised, watchful, hand resting on hilt" 768 900 cut
gen_2d samurai_annoyed 320 "$SAMURAI, annoyed frown, thumb pushing the katana guard, ten centimeters of blade showing" 768 900 cut
gen_2d samurai_angry 320 "$SAMURAI, angry glare, half the blade drawn and gleaming" 768 900 cut
gen_2d samurai_fury 320 "$SAMURAI, furious wide-eyed glare, katana fully drawn overhead ready to slash" 768 900 cut
gen_2d title_art 330 "the word SANDONIETTE in giant dramatic japanese calligraphy brush strokes, black sumi ink" 1024 768 cut
gen_2d ticket_paper 340 "a single blank narrow paper order ticket, faint fold marks, plain, no text" 512 640
gen_2d slash_frame 350 "one single diagonal white katana slash streak on transparent background, motion blur, sharp" 1024 1024 cut
# food faces — comical, slightly alarmed
gen_2d face_bread 360 "a comical slightly alarmed cartoon face for a slice of bread, simple cut-out paper eyes and mouth, worried" 512 512 cut
gen_2d face_tomato 362 "a comical nervous cartoon face for a round tomato, simple cut-out paper features, sweating" 512 512 cut
gen_2d face_cheese 364 "a comical dopey cartoon face for a wedge of cheese, simple cut-out paper features" 512 512 cut
gen_2d face_katsu 366 "a comical brave cartoon face for a breaded pork katsu cutlet, simple cut-out paper features" 512 512 cut
gen_2d face_egg 368 "a comical wide-eyed cartoon face for a boiled egg, simple cut-out paper features, startled" 512 512 cut
# splat decals
gen_2d splat_wet 370 "a single messy wet food splat splatter shape, flat black silhouette, on transparent background" 512 512 cut
echo "done."