Generate a complete 2D game character sprite sheet (4 rows × 10 columns = 40 frames) from a reference image. Each row represents one direction, containing: 1 standing frame + 3 walking frames + 3 running frames + 3 death frames. The final output is a single transparent-background PNG.
Final Layout (4 rows × 10 columns):
| Col | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| ----- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Row 1 (Left) | stand | walk1 | walk2 | walk3 | run1 | run2 | run3 | death1 | death2 | death3 |
| Row 2 (Front) | stand | walk1 | walk2 | walk3 | run1 | run2 | run3 | death1 | death2 | death3 |
| Row 3 (Right) | stand | walk1 | walk2 | walk3 | run1 | run2 | run3 | death1 | death2 | death3 |
| Row 4 (Back) | stand | walk1 | walk2 | walk3 | run1 | run2 | run3 | death1 | death2 | death3 |
Collect from the user:
| Parameter | Required | Default | Description |
|---|---|---|---|
| ----------- | ---------- | --------- | ------------- |
| Reference image(s) | Yes | — | 1 image (single character) OR 4 images (left/front/right/back standing frames) |
| Frame size | No | 200×200 px | Width × Height of each individual frame |
| Output directory | No | generated-images/ | Where to save generated frames and final sheet |
If the user does not specify a frame size, default to 200px × 200px.
Read the reference image(s) using read_file to understand the character's visual appearance (art style, colors, proportions, clothing, accessories, etc.). Write a detailed [CHARACTER_DESCRIPTION] based on what you see. This description will be used in ALL subsequent generation prompts.
The single image serves as one direction's standing frame. Generate the other 3 directions:
read_file to analyze the character thoroughlyimage_gen to generate the remaining 3 directions in parallel, with prompts that explicitly reference the original image's style:Prompt template for generating missing standing frames:
Based on the provided reference character image, generate the exact same character in [DIRECTION] view as a 2D game sprite. Standing idle pose. The character must have identical: art style, color palette, proportions, clothing, accessories, and level of detail as the reference. Single character centered on pure white background, full body visible, clean lines, [WIDTH]x[HEIGHT] resolution.
Save all 4 standing frames as: left_stand.png, front_stand.png, right_stand.png, back_stand.png
Map each image to its direction (left/front/right/back). Save them with the standard naming.
After obtaining 4 standing frames, display all 4 to the user using read_file on each image, and ask for confirmation:
> "Here are the 4 directional standing frames. Please confirm they look correct before I generate the animation frames:
> - Left standing frame
> - Front standing frame
> - Right standing frame
> - Back standing frame
>
> Should I proceed with generating walk/run/death animations based on these?"
Do NOT proceed until the user confirms. If the user requests changes, regenerate the affected frames and confirm again.
Process each direction one at a time in this order: Left → Front → Right → Back.
For each direction:
read_file — this ensures the AI sees the exact reference before generatingEach generated frame must reference the standing frame's visual style.
| Frame | Pose |
|---|---|
| ------- | ------ |
| Walk 1 | Left foot forward, right foot back, arms swinging opposite to legs |
| Walk 2 | Feet passing center, transitional mid-stride pose, weight centered |
| Walk 3 | Right foot forward, left foot back, arms swinging opposite to legs |
Prompt template:
Based on the provided reference character standing pose, generate the exact same character as a 2D game sprite walking animation frame [N] of 3, [DIRECTION] view. [WALK_POSE_DESCRIPTION]. The character must have identical: art style, color palette, proportions, clothing, accessories as the reference standing pose. Single character centered on pure white background, full body visible, clean lines, [WIDTH]x[HEIGHT] resolution.
Walk pose descriptions:
left leg stepping forward, right leg back, left arm swinging back right arm forward, mid-stride walking motionlegs passing through center, transitional pose, weight centered, brief standing transition between stepsright leg stepping forward, left leg back, right arm swinging back left arm forward, mid-stride walking motionSave as: {direction}_walk_1.png, {direction}_walk_2.png, {direction}_walk_3.png
| Frame | Pose |
|---|---|
| ------- | ------ |
| Run 1 | Push-off, back leg extended, front knee high |
| Run 2 | Airborne flight phase, both feet off ground |
| Run 3 | Landing, front foot striking ground, body leaning forward |
Prompt template:
Based on the provided reference character standing pose, generate the exact same character as a 2D game sprite running animation frame [N] of 3, [DIRECTION] view. [RUN_POSE_DESCRIPTION]. Dynamic motion. The character must have identical: art style, color palette, proportions, clothing, accessories as the reference standing pose. Single character centered on pure white background, full body visible, clean lines, [WIDTH]x[HEIGHT] resolution.
Run pose descriptions:
push-off pose, back leg fully extended, front knee raised high, arms pumping vigorouslyairborne flight phase, both feet off ground, knees tucked, arms mid-swing at peak of stridelanding pose, front foot striking ground, body leaning forward, arms countering momentumSave as: {direction}_run_1.png, {direction}_run_2.png, {direction}_run_3.png
| Frame | Pose |
|---|---|
| ------- | ------ |
| Death 1 | Stumbling, body tilting, knees buckling |
| Death 2 | Fallen on the ground, lying flat |
| Death 3 | Fading/dissolving, semi-transparent, disappearing |
Prompt template:
Based on the provided reference character standing pose, generate the exact same character as a 2D game sprite death animation frame [N] of 3, [DIRECTION] view. [DEATH_POSE_DESCRIPTION]. The character must have identical: art style, color palette, proportions, clothing, accessories as the reference standing pose. Single character centered on pure white background, full body visible, clean lines, [WIDTH]x[HEIGHT] resolution.
Death pose descriptions:
stumbling and collapsing, body tilting sideways, knees buckling, arms flailing, moment of impactlying flat on the ground, defeated pose, body sprawled out, completely fallen, motionlessfading away and dissolving, semi-transparent ghostly effect, particles dispersing, disappearingSave as: {direction}_death_1.png, {direction}_death_2.png, {direction}_death_3.png
For each direction, the processing flow is:
read_file({direction}_stand.png)
→ generate {direction}_walk_1/2/3.png (referencing standing frame)
→ generate {direction}_run_1/2/3.png (referencing standing frame)
→ generate {direction}_death_1/2/3.png (referencing standing frame)
Process order: Left → Front → Right → Back.
Within each direction, walk/run/death frames can be generated in parallel (up to 9 image_gen calls simultaneously), since they all reference the same standing frame already loaded via read_file.
After all 40 frames are generated, write the following Python script to {OUTPUT_DIR}/merge_sprite_sheet.py and execute it.
Run command:
pip install Pillow && python3 {OUTPUT_DIR}/merge_sprite_sheet.py --input-dir {OUTPUT_DIR} --output {OUTPUT_DIR}/sprite_sheet.png --frame-width {W} --frame-height {H}
Full script content to write:
#!/usr/bin/env python3
"""
Sprite Sheet Merger — 4 rows x 10 columns = 40 frames.
Layout:
Row 1 (Left): stand, walk_1, walk_2, walk_3, run_1, run_2, run_3, death_1, death_2, death_3
Row 2 (Front): stand, walk_1, walk_2, walk_3, run_1, run_2, run_3, death_1, death_2, death_3
Row 3 (Right): stand, walk_1, walk_2, walk_3, run_1, run_2, run_3, death_1, death_2, death_3
Row 4 (Back): stand, walk_1, walk_2, walk_3, run_1, run_2, run_3, death_1, death_2, death_3
Usage:
python3 merge_sprite_sheet.py --input-dir <dir> --output <path> [--frame-width W] [--frame-height H]
"""
import argparse
import sys
from pathlib import Path
try:
from PIL import Image
except ImportError:
print("Error: Pillow is required. Install with: pip install Pillow")
sys.exit(1)
COLS = 10
ROWS = 4
DIRECTIONS = ["left", "front", "right", "back"]
def build_layout():
"""Build the 4x10 layout grid."""
layout = []
for row_idx, direction in enumerate(DIRECTIONS):
frame_names = [
f"{direction}_stand",
f"{direction}_walk_1", f"{direction}_walk_2", f"{direction}_walk_3",
f"{direction}_run_1", f"{direction}_run_2", f"{direction}_run_3",
f"{direction}_death_1", f"{direction}_death_2", f"{direction}_death_3",
]
layout.append((row_idx, direction, frame_names))
return layout
def find_image(input_dir: Path, name: str):
"""Find an image file by name (without extension) in the input directory."""
for ext in [".png", ".jpg", ".jpeg", ".webp"]:
candidate = input_dir / f"{name}{ext}"
if candidate.exists():
return candidate
return None
def remove_white_background(img: Image.Image, threshold: int = 240) -> Image.Image:
"""Convert white/near-white pixels to transparent."""
img = img.convert("RGBA")
pixels = img.load()
width, height = img.size
for y in range(height):
for x in range(width):
r, g, b, a = pixels[x, y]
if r >= threshold and g >= threshold and b >= threshold:
pixels[x, y] = (r, g, b, 0)
return img
def load_and_resize(path: Path, frame_width: int, frame_height: int, remove_bg: bool = True) -> Image.Image:
"""Load an image, resize to frame dimensions, optionally remove white background."""
img = Image.open(path).convert("RGBA")
img.thumbnail((frame_width, frame_height), Image.LANCZOS)
canvas = Image.new("RGBA", (frame_width, frame_height), (0, 0, 0, 0))
offset_x = (frame_width - img.width) // 2
offset_y = (frame_height - img.height) // 2
canvas.paste(img, (offset_x, offset_y), img)
if remove_bg:
canvas = remove_white_background(canvas)
return canvas
def merge_sprite_sheet(input_dir: str, output: str, frame_width: int = 200, frame_height: int = 200) -> bool:
"""Merge individual frames into a 4x10 sprite sheet."""
input_path = Path(input_dir)
if not input_path.exists():
print(f"Error: Input directory not found: {input_dir}")
return False
sheet_width = COLS * frame_width
sheet_height = ROWS * frame_height
print(f"Sprite sheet: {sheet_width}x{sheet_height} ({COLS} cols x {ROWS} rows)")
print(f"Frame size: {frame_width}x{frame_height}")
print()
sheet = Image.new("RGBA", (sheet_width, sheet_height), (0, 0, 0, 0))
layout = build_layout()
total_frames = 0
missing_frames = []
for row_idx, direction, frame_names in layout:
for col_idx, frame_name in enumerate(frame_names):
img_path = find_image(input_path, frame_name)
if img_path is None:
missing_frames.append(frame_name)
print(f" ⚠ Missing: {frame_name}")
continue
frame_img = load_and_resize(img_path, frame_width, frame_height)
x = col_idx * frame_width
y = row_idx * frame_height
sheet.paste(frame_img, (x, y), frame_img)
total_frames += 1
print(f" ✓ [{direction}] {frame_name} → col {col_idx+1} ({x}, {y})")
output_path = Path(output)
output_path.parent.mkdir(parents=True, exist_ok=True)
sheet.save(str(output_path), "PNG")
print()
print(f"✅ Sprite sheet saved: {output_path}")
print(f" Frames placed: {total_frames}/40")
if missing_frames:
print(f" Missing ({len(missing_frames)}): {', '.join(missing_frames)}")
return total_frames == 40
def main():
parser = argparse.ArgumentParser(description="Merge sprite frames into a 4x10 sprite sheet")
parser.add_argument("--input-dir", required=True, help="Directory containing frame PNGs")
parser.add_argument("--output", required=True, help="Output sprite sheet path")
parser.add_argument("--frame-width", type=int, default=200, help="Frame width (default: 200)")
parser.add_argument("--frame-height", type=int, default=200, help="Frame height (default: 200)")
args = parser.parse_args()
success = merge_sprite_sheet(
input_dir=args.input_dir,
output=args.output,
frame_width=args.frame_width,
frame_height=args.frame_height,
)
sys.exit(0 if success else 1)
if __name__ == "__main__":
main()
After merging, you must validate the result before presenting to the user. This step is mandatory and cannot be skipped.
Read the output sprite sheet with read_file and verify:
(10 × frame_width) by (4 × frame_height)For each row, visually compare frames 2–10 against frame 1 (the standing frame) of that row:
Check these aspects:
Validation method:
read_fileIf validation fails for any frames:
read_fileBased on the provided reference character standing pose, generate the EXACT same character as a 2D game sprite [ACTION] frame. [DIRECTION] view. [POSE_DESCRIPTION]. CRITICAL: The character MUST have exactly the same [SPECIFIC_ISSUE] as the reference. Match precisely: art style, color palette, proportions, clothing, accessories. Single character centered on pure white background, full body visible, clean lines, [WIDTH]x[HEIGHT] resolution.
Repeat this fix cycle until ALL 40 frames pass validation.
Maximum retry attempts: 3 per failed frame. If a frame still fails after 3 retries, inform the user and present the best version available.
Only after validation passes:
read_file on the output PNGRow 1 (Left): [stand] [walk1] [walk2] [walk3] [run1] [run2] [run3] [death1] [death2] [death3]
Row 2 (Front): [stand] [walk1] [walk2] [walk3] [run1] [run2] [run3] [death1] [death2] [death3]
Row 3 (Right): [stand] [walk1] [walk2] [walk3] [run1] [run2] [run3] [death1] [death2] [death3]
Row 4 (Back): [stand] [walk1] [walk2] [walk3] [run1] [run2] [run3] [death1] [death2] [death3]
Based on the provided reference character standing pose to force the AI to reference the standing frameread_file on that direction's standing frame first — this loads the visual reference into contextimage_gen calls)image_gen calls)image_gen fails for any frame, retry once with a simplified promptpip install Pillow before running共 1 个版本