Office Sprite Generator
Create game-ready sprites for the Claude Office Visualizer using Nano Banana MCP and ImageMagick.
Project Context
The Claude Office Visualizer uses a 45-degree front/top-down perspective (NOT isometric). This means:
- •Objects are viewed primarily from the front
- •Slight top-down angle shows a bit of the top surface
- •You do NOT see multiple side faces like in isometric views
- •Similar to classic 2D RPGs or top-down office games
Art Style: Retro 16-bit pixel art with clean edges and limited anti-aliasing.
Workflow
Step 1: Generate with Nano Banana
Use mcpl to call Nano Banana with this prompt template:
mcpl call nanobanana generate_image '{
"prompt": "[OBJECT DESCRIPTION], front view with slight top-down angle, NOT isometric, pixel art style, retro 16-bit game sprite, isolated on solid magenta background #FF00FF, clean edges, no shadows on background, game sprite asset, centered composition, no text, no watermarks, simple design",
"output_path": "/Users/probello/Repos/claude-office/frontend/public/sprites/[NAME]_raw.png"
}'
Prompt Variables:
- •
[OBJECT DESCRIPTION]: Detailed description of the object (e.g., "Office water cooler dispenser with blue water bottle jug on top of white dispenser stand with hot and cold taps") - •
[NAME]: Sprite filename (e.g., "watercooler", "desk", "plant")
Step 2: VALIDATE THE IMAGE
CRITICAL: Before proceeding with ImageMagick processing, you MUST:
- •
Copy the generated image to the raw location:
bashcp "/Users/probello/nanobanana-images/temp_images/[UUID].png" \ "/Users/probello/Repos/claude-office/frontend/public/sprites/[NAME]_raw.png"
- •
View the image using the Read tool to verify:
- •Perspective is correct (front view, NOT isometric/3D cube view)
- •Subject is centered and fully visible
- •Background is solid magenta (may have black letterboxing on sides)
- •Art style matches retro pixel art aesthetic
- •
If the image is NOT correct:
- •Regenerate with adjusted prompt
- •Do NOT proceed to ImageMagick processing
- •Common issues:
- •Isometric view: Add "NOT isometric, front facing view" more emphatically
- •Wrong style: Specify "16-bit pixel art, retro game sprite" more clearly
- •Cut off subject: Add "full object visible, not cropped"
Step 3: Process with ImageMagick
Only after validation passes, remove the magenta background using the helper script:
# Using the helper script (recommended) /Users/probello/Repos/claude-office/.claude/skills/office-sprite/scripts/process_sprite.sh \ /Users/probello/Repos/claude-office/frontend/public/sprites/[NAME]_raw.png \ /Users/probello/Repos/claude-office/frontend/public/sprites/[NAME].png
The script uses a multi-pass workflow combining FFmpeg and ImageMagick:
- •FFmpeg geq filter: Removes pixels where R≈B and G is low (purple/magenta hues)
- •ImageMagick multi-pass: Catches remaining bright magenta shades (#FF00FF, #CC00CC, etc.)
- •ImageMagick dark purple cleanup: Removes dark edge pixels like rgb(32,0,31)
For legacy flood-fill method (faster but may leave pink edges):
process_sprite.sh input.png output.png --legacy
Manual multi-pass workflow (if script unavailable):
INPUT="/Users/probello/Repos/claude-office/frontend/public/sprites/[NAME]_raw.png" OUTPUT="/Users/probello/Repos/claude-office/frontend/public/sprites/[NAME].png" # Step 1: FFmpeg - remove purple hue pixels (R≈B, G low) ffmpeg -y -i "$INPUT" \ -vf "geq=r='r(X,Y)':g='g(X,Y)':b='b(X,Y)':a='if(between(r(X,Y)-b(X,Y),-60,60)*lt(g(X,Y),r(X,Y)*0.7)*lt(g(X,Y),b(X,Y)*0.7)*gt(r(X,Y)+b(X,Y),100),0,alpha(X,Y))'" \ -update 1 -frames:v 1 /tmp/step1.png # Step 2: ImageMagick - remove bright magenta shades magick /tmp/step1.png -alpha set -channel RGBA \ -fuzz 20% -transparent "magenta" \ -fuzz 15% -transparent "#CC00CC" \ -fuzz 15% -transparent "#880088" \ -fuzz 15% -transparent "#660066" \ /tmp/step2.png # Step 3: ImageMagick - remove dark purple edge pixels magick /tmp/step2.png \ -fuzz 8% -fill none \ -opaque "rgb(32,0,31)" \ -opaque "rgb(34,0,31)" \ -trim +repage -strip \ "$OUTPUT" # Verify transparency magick "$OUTPUT" -format "Size: %wx%h, Opaque: %[opaque]" info:
Why multi-pass? AI-generated images often have anti-aliased edges that blend the subject with the magenta background. Single-pass removal leaves pink/purple fringing. The multi-pass approach targets different shades of magenta/purple for thorough cleanup
Step 4: Verify Final Sprite
View the processed sprite with the Read tool to confirm:
- •Clean transparency (no magenta fringing)
- •Sprite edges are intact (not eroded)
- •Correct dimensions for game use
Step 5: Update Game Code
In OfficeGameV2.tsx, sprites are loaded and displayed like this:
// Add texture state
const [spriteTexture, setSpriteTexture] = useState<Texture | null>(null);
// Load texture in useEffect
useEffect(() => {
const loadTextures = async () => {
try {
const texture = await Assets.load("/sprites/[NAME].png");
setSpriteTexture(texture);
} catch (e) {
console.warn("Failed to load sprite:", e);
}
};
loadTextures();
}, []);
// Render sprite with fallback to placeholder
<pixiContainer x={X_POS} y={Y_POS}>
{spriteTexture ? (
<pixiSprite
texture={spriteTexture}
anchor={0.5}
scale={SCALE_FACTOR}
/>
) : (
<pixiGraphics draw={drawPlaceholder} />
)}
</pixiContainer>
Scale Calculation:
- •Target display width / Sprite actual width = scale factor
- •Example: For 50px display width with 189px sprite:
scale={50/189}orscale={0.26}
Furniture Reference
Current furniture sizes from furnitureManager.ts:
| Type | Width | Height | Notes |
|---|---|---|---|
| desk | 140px | 80px | With chair position |
| plant | 40px | 40px | Potted plant |
| watercooler | 50px | 50px | Water dispenser |
| filing_cabinet | 60px | 80px | Metal cabinet |
| couch | 120px | 60px | Office couch |
| table | 100px | 60px | Meeting table |
Additional elements from OfficeGameV2.tsx:
| Element | Approx Size | Notes |
|---|---|---|
| Wall clock | 88x88px | Analog clock face |
| Whiteboard | 330x170px | With todo display |
| Elevator | 128x160px | With doors |
| Safety sign | 140x100px | Days without incident |
Output Location
All sprites go to: /Users/probello/Repos/claude-office/frontend/public/sprites/
- •
[name]_raw.png- Original generated image (keep for reference) - •
[name].png- Processed sprite with transparency
Anti-Patterns
DO NOT:
- •Skip the validation step - always view the raw image first
- •Use
-transparentinstead of flood fill - it removes ALL matching pixels - •Proceed with isometric/wrong perspective images - regenerate instead
- •Use white or black as chroma key - they appear in subjects
- •Forget to trim - wastes texture memory
DO:
- •Always validate before processing
- •Use flood fill from corners for clean background removal
- •Keep raw images as backup
- •Verify final sprite has transparency (
Opaque: False) - •Test sprite in game before moving to next asset