office-sprite

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Office Sprite Generator

Office精灵图生成指南

Create game-ready sprites for the Claude Office Visualizer using Nano Banana MCP and ImageMagick.
为Claude Office Visualizer创建可直接用于游戏的精灵图,使用Nano Banana MCP和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.
Claude Office Visualizer采用45度前俯视角(非等轴测视角)。这意味着:
  • 物体主要从正面展示
  • 轻微的俯角可显示少量顶面
  • 不会像等轴测视图那样显示多个侧面
  • 类似经典2D RPG或俯视角办公室游戏的视角
美术风格:复古16位像素美术,边缘清晰,抗锯齿效果有限。

Workflow

工作流程

Step 1: Generate with Nano Banana

步骤1:使用Nano Banana生成

Use mcpl to call Nano Banana with this prompt template:
bash
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")
使用mcpl调用Nano Banana,采用以下提示模板:
bash
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"
}'
提示变量说明:
  • [OBJECT DESCRIPTION]
    :物体的详细描述(例如:"办公室饮水机,白色机身顶部放置蓝色水桶,带有冷热出水龙头")
  • [NAME]
    :精灵图文件名(例如:"watercooler"、"desk"、"plant")

Step 2: VALIDATE THE IMAGE

步骤2:验证图片

CRITICAL: Before proceeding with ImageMagick processing, you MUST:
  1. Copy the generated image to the raw location:
    bash
    cp "/Users/probello/nanobanana-images/temp_images/[UUID].png" \
       "/Users/probello/Repos/claude-office/frontend/public/sprites/[NAME]_raw.png"
  2. 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
  3. 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"
重要提示:在进行ImageMagick处理之前,您必须:
  1. 将生成的图片复制到原始文件目录:
    bash
    cp "/Users/probello/nanobanana-images/temp_images/[UUID].png" \
       "/Users/probello/Repos/claude-office/frontend/public/sprites/[NAME]_raw.png"
  2. 使用查看工具查看图片,验证以下内容:
    • 视角正确(正面视图,非等轴测/3D立方体视图)
    • 主体居中且完整可见
    • 背景为纯品红色(两侧可能有黑边)
    • 美术风格匹配复古像素美术审美
  3. 如果图片不符合要求:
    • 调整提示词重新生成
    • 不要进行ImageMagick处理
    • 常见问题:
      • 等轴测视图:更强调地添加"NOT isometric, front facing view"
      • 风格错误:更明确地指定"16-bit pixel art, retro game sprite"
      • 主体被裁剪:添加"full object visible, not cropped"

Step 3: Process with ImageMagick

步骤3:使用ImageMagick处理

Only after validation passes, remove the magenta background using the helper script:
bash
undefined
只有在验证通过后,才能使用辅助脚本移除品红色背景:
bash
undefined

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:

1. **FFmpeg geq filter**: Removes pixels where R≈B and G is low (purple/magenta hues)
2. **ImageMagick multi-pass**: Catches remaining bright magenta shades (#FF00FF, #CC00CC, etc.)
3. **ImageMagick dark purple cleanup**: Removes dark edge pixels like rgb(32,0,31)

For legacy flood-fill method (faster but may leave pink edges):
```bash
process_sprite.sh input.png output.png --legacy
Manual multi-pass workflow (if script unavailable):
bash
INPUT="/Users/probello/Repos/claude-office/frontend/public/sprites/[NAME]_raw.png"
OUTPUT="/Users/probello/Repos/claude-office/frontend/public/sprites/[NAME].png"
/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

该脚本结合FFmpeg和ImageMagick采用**多阶段处理流程**:

1. **FFmpeg geq滤镜**:移除R≈B且G值较低的像素(紫色/品红色调)
2. **ImageMagick多阶段处理**:捕获剩余的亮品红色调(#FF00FF、#CC00CC等)
3. **ImageMagick深紫色清理**:移除深紫色边缘像素,如rgb(32,0,31)

如需使用传统的漫水填充方法(速度更快但可能留下粉色边缘):
```bash
process_sprite.sh input.png output.png --legacy
手动多阶段处理流程(当脚本不可用时):
bash
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)

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
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

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
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

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"
magick /tmp/step2.png
-fuzz 8% -fill none
-opaque "rgb(32,0,31)"
-opaque "rgb(34,0,31)"
-trim +repage -strip
"$OUTPUT"

Verify transparency

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
magick "$OUTPUT" -format "Size: %wx%h, Opaque: %[opaque]" info:

**为什么要多阶段处理?** AI生成的图像通常带有抗锯齿边缘,会使主体与品红色背景融合。单阶段移除会留下粉色/紫色边缘。多阶段处理针对不同色调的品红/紫色进行彻底清理。

Step 4: Verify Final Sprite

步骤4:验证最终精灵图

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

步骤5:更新游戏代码

In
OfficeGameV2.tsx
, sprites are loaded and displayed like this:
typescript
// 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}
    or
    scale={0.26}
OfficeGameV2.tsx
中,精灵图的加载和显示方式如下:
typescript
// 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>
缩放计算:
  • 目标显示宽度 / 精灵图实际宽度 = 缩放系数
  • 示例:对于显示宽度50px、实际宽度189px的精灵图:
    scale={50/189}
    scale={0.26}

Furniture Reference

家具参考

Current furniture sizes from
furnitureManager.ts
:
TypeWidthHeightNotes
desk140px80pxWith chair position
plant40px40pxPotted plant
watercooler50px50pxWater dispenser
filing_cabinet60px80pxMetal cabinet
couch120px60pxOffice couch
table100px60pxMeeting table
Additional elements from
OfficeGameV2.tsx
:
ElementApprox SizeNotes
Wall clock88x88pxAnalog clock face
Whiteboard330x170pxWith todo display
Elevator128x160pxWith doors
Safety sign140x100pxDays without incident
来自
furnitureManager.ts
的当前家具尺寸:
类型宽度高度说明
desk140px80px包含椅子位置
plant40px40px盆栽植物
watercooler50px50px饮水机
filing_cabinet60px80px金属文件柜
couch120px60px办公沙发
table100px60px会议桌
来自
OfficeGameV2.tsx
的其他元素:
元素近似尺寸说明
Wall clock88x88px模拟时钟表盘
Whiteboard330x170px包含待办事项显示
Elevator128x160px带门的电梯
Safety sign140x100px无事故天数标识

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
所有精灵图保存至:
/Users/probello/Repos/claude-office/frontend/public/sprites/
  • [name]_raw.png
    - 原始生成图像(保留作为参考)
  • [name].png
    - 带透明背景的处理后精灵图

Anti-Patterns

反模式(错误做法)

DO NOT:
  • Skip the validation step - always view the raw image first
  • Use
    -transparent
    instead 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
请勿:
  • 跳过验证步骤 - 务必先查看原始图像
  • 使用
    -transparent
    替代漫水填充 - 它会移除所有匹配像素
  • 继续使用等轴测/错误视角的图像 - 重新生成
  • 使用白色或黑色作为色度键 - 它们会出现在主体中
  • 忘记裁剪 - 浪费纹理内存
请:
  • 处理前始终进行验证
  • 使用从角落开始的漫水填充来干净地移除背景
  • 保留原始图像作为备份
  • 验证最终精灵图是否具有透明效果(
    Opaque: False
  • 在处理下一个资源前,先在游戏中测试精灵图