Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 09:06:21 +08:00
commit 4de211b5a8
23 changed files with 8919 additions and 0 deletions

View File

@@ -0,0 +1,746 @@
---
name: Pixel Art Exporter
description: Export sprites to PNG, GIF, or spritesheet formats with JSON metadata for game engines. Use when the user wants to "export", "save", "output", "render", "generate", "create file", mentions file formats like "PNG", "GIF", "animated GIF", "spritesheet", "sprite sheet", "texture atlas", "tile sheet", or game engine integration with "Unity", "Godot", "Phaser", "Unreal", "GameMaker". Trigger on layout terms ("horizontal", "vertical", "grid", "packed", "strip"), scaling ("2x", "4x", "upscale", "pixel-perfect"), file operations ("save as", "export to", "output to"), metadata formats ("JSON", "XML", "metadata", "atlas data"), and delivery terms ("for web", "for game", "for Twitter", "for itch.io", "optimized").
allowed-tools: Read, Bash, mcp__aseprite__export_png, mcp__aseprite__export_gif, mcp__aseprite__export_spritesheet, mcp__aseprite__get_sprite_info
---
# Pixel Art Exporter
## Overview
The Pixel Art Exporter Skill enables exporting pixel art sprites from Aseprite to various formats optimized for different use cases. This includes single images (PNG), animated GIFs, spritesheets, and JSON metadata for game engines.
**Core Capabilities:**
- Export single frames or entire animations as PNG images
- Generate animated GIFs with customizable timing and looping
- Create spritesheets in multiple layouts (horizontal, vertical, grid, packed)
- Generate JSON metadata for game engines (Unity, Godot, Phaser, generic)
- Scale exports with pixel-perfect upscaling (1x, 2x, 4x, etc.)
- Handle transparency, background colors, and frame-specific exports
**Export Formats Supported:**
- **PNG**: Single images or frame sequences with transparency
- **GIF**: Animated GIFs with frame timing and loop control
- **Spritesheet**: Texture atlases with various packing algorithms
- **JSON**: Frame metadata, animation tags, layer information
This Skill works with the pixel-mcp server tools to produce production-ready assets for web, games, and applications.
## When to Use
Invoke this Skill when the user:
- **Wants to export or save**: "export this sprite", "save as PNG", "generate a spritesheet"
- **Mentions file formats**: "PNG", "GIF", "spritesheet", "sprite sheet", "texture atlas", "JSON"
- **Prepares for game engines**: "export for Unity", "Godot spritesheet", "Phaser animation"
- **Needs specific outputs**: "export just frame 3", "create a tileset", "save each layer separately"
- **Requests scaling**: "export at 2x size", "scale up 4x", "upscale for retina displays"
- **Wants animation exports**: "make this into a GIF", "export the animation", "save all frames"
- **Needs metadata**: "include JSON data", "export with coordinates", "frame information"
**Example Triggers:**
- "Can you export this character sprite as a PNG?"
- "I need a spritesheet for my game engine"
- "Save this animation as an animated GIF"
- "Export at 4x scale for high-resolution displays"
- "Generate a texture atlas with JSON metadata"
- "Export just the 'run' animation tag"
## Instructions
### 1. Exporting Single Images (PNG)
**For static sprites or single frames:**
1. **Get Sprite Information First**
```
Use mcp__aseprite__get_sprite_info to understand:
- Current dimensions
- Number of frames
- Available layers
- Color mode and transparency settings
```
2. **Export PNG with Transparency**
```
Use mcp__aseprite__export_png:
- file_path: Absolute path (e.g., "/path/to/output/sprite.png")
- frame_number: Specific frame (0-indexed) or omit for current frame
- layer: Specific layer name or omit for merged output
- scale: Scaling factor (1, 2, 4, etc.) - default is 1
```
3. **Export Options**
- **Transparent background**: Default behavior, preserves alpha channel
- **Specific background**: Use layer visibility or flatten before export
- **Single frame from animation**: Specify frame_number parameter
- **Specific layer only**: Provide layer name to export just that layer
**Example Workflow:**
```
1. Get sprite info to verify dimensions and frame count
2. Export PNG: mcp__aseprite__export_png with desired frame and scale
3. Confirm file creation and report dimensions to user
```
### 2. Exporting Animated GIFs
**For animations intended for web or presentations:**
1. **Verify Animation Setup**
```
Use mcp__aseprite__get_sprite_info to check:
- Frame count (needs 2+ frames)
- Frame durations (timing information)
- Animation tags (if specific tag requested)
- Sprite dimensions
```
2. **Export GIF**
```
Use mcp__aseprite__export_gif:
- file_path: Output path (e.g., "/path/to/animation.gif")
- animation_tag: Optional - specific tag name to export
- loop: true (infinite loop) or false (play once)
- scale: Upscaling factor if needed
```
3. **GIF Optimization Considerations**
- GIF format has 256-color limit - ensure palette is optimized
- Frame timing is preserved from Aseprite frame durations
- Transparency is supported but may have edge artifacts
- File size increases with dimensions and frame count
**Example Workflow:**
```
1. Verify sprite has multiple frames
2. Export GIF with appropriate loop setting
3. Report file size and frame count to user
4. Suggest optimization if file is large (>1MB)
```
### 3. Creating Spritesheets
**For game engines and texture atlases:**
1. **Understand Layout Requirements**
**Layout Types:**
- **Horizontal**: All frames in a single row (good for scrolling animations)
- **Vertical**: All frames in a single column (good for CSS animations)
- **Grid**: Frames arranged in rows and columns (balanced dimensions)
- **Packed**: Optimized packing to minimize texture size (engine-specific)
2. **Export Spritesheet**
```
Use mcp__aseprite__export_spritesheet:
- file_path: Output PNG path (e.g., "/path/to/spritesheet.png")
- layout: "horizontal", "vertical", "grid", or "packed"
- animation_tag: Optional - export specific animation only
- scale: Upscaling factor
- padding: Pixels between frames (default 0, common: 1-2)
- include_json: true to generate metadata file
```
3. **JSON Metadata Structure**
When `include_json: true`, creates a .json file with:
```json
{
"frames": [
{
"filename": "frame_0.png",
"frame": {"x": 0, "y": 0, "w": 32, "h": 32},
"spriteSourceSize": {"x": 0, "y": 0, "w": 32, "h": 32},
"sourceSize": {"w": 32, "h": 32},
"duration": 100
}
],
"meta": {
"app": "Aseprite",
"version": "1.3.x",
"format": "RGBA8888",
"size": {"w": 256, "h": 32},
"scale": "1"
}
}
```
4. **Layout Selection Guidelines**
- **Horizontal**: Best for web/CSS sprite animations, simple scrolling
- **Vertical**: Mobile-friendly, vertical scrolling animations
- **Grid**: Unity, Godot - balanced texture dimensions (power-of-2)
- **Packed**: Advanced engines with atlas support (Phaser, LibGDX)
**Example Workflow:**
```
1. Ask user about target platform if not specified
2. Recommend layout based on use case
3. Export spritesheet with JSON metadata
4. Report texture dimensions and frame count
5. Provide integration code sample for their engine
```
### 4. Generating JSON Metadata
**For game engine integration:**
1. **Metadata Formats by Engine**
**Unity:**
- Use "grid" layout for Unity's Sprite Editor
- JSON provides frame coordinates for slicing
- Include padding to prevent texture bleeding
**Godot:**
- Use "horizontal" or "grid" layout
- JSON maps to AnimatedSprite frames
- Frame duration converts to FPS
**Phaser:**
- Use "packed" layout for optimal performance
- JSON follows Texture Packer format
- Supports trimmed sprites and rotation
**Generic/Custom:**
- Standard frame array with x, y, w, h coordinates
- Duration in milliseconds per frame
- Animation tag groupings
2. **Export with Metadata**
```
Always include JSON when exporting for game engines:
- Set include_json: true in export_spritesheet
- JSON file created with same name as PNG (different extension)
- Contains frame positions, durations, and sprite metadata
```
3. **Metadata Usage Examples**
**Parsing in JavaScript (Phaser):**
```javascript
this.load.atlas('sprite', 'spritesheet.png', 'spritesheet.json');
this.add.sprite(x, y, 'sprite', 'frame_0.png');
```
**Parsing in C# (Unity):**
```csharp
// Import spritesheet.png with Multiple sprite mode
// Use JSON to set sprite rectangles in Sprite Editor
```
### 5. Scaling Exports
**Pixel-perfect upscaling for high-resolution displays:**
1. **When to Scale**
- Retina/HiDPI displays: Use 2x or 4x
- Modern game engines: Export at native size, let engine scale
- Web: Export 2x and use CSS to scale down (sharper rendering)
- Print/marketing: Use 4x or higher
2. **Scaling Best Practices**
- Always use integer scaling (1x, 2x, 3x, 4x, not 1.5x)
- Maintain pixel-perfect sharpness with nearest-neighbor
- Scale before export, not after (prevents blurring)
- Consider file size vs. quality tradeoffs
3. **Apply Scaling**
```
Add scale parameter to any export:
- mcp__aseprite__export_png: scale: 2
- mcp__aseprite__export_gif: scale: 4
- mcp__aseprite__export_spritesheet: scale: 2
```
4. **Resolution Recommendations**
- **1x**: Original pixel art size, retro aesthetic
- **2x**: Standard for modern displays, good balance
- **4x**: High-resolution, marketing materials
- **8x+**: Ultra-high-resolution, print, large displays
## Export Workflows for Different Use Cases
### Static Sprite for Web
```
1. Get sprite info to verify single frame
2. Export PNG at 2x scale with transparency
3. Optimize PNG with compression tools if needed
4. Provide HTML/CSS example for display
```
### Character Animation for Game
```
1. Verify animation has multiple frames and tags
2. Export spritesheet with "grid" layout
3. Include JSON metadata (include_json: true)
4. Set appropriate padding (1-2 pixels)
5. Scale if needed (typically 1x for engines)
6. Provide code snippet for target engine
```
### Icon Set Export
```
1. If multiple layers, export each separately
2. Use PNG format with transparency
3. Scale to multiple sizes (16x16, 32x32, 64x64)
4. Batch export all sizes
5. Organize in output directory structure
```
### Social Media GIF
```
1. Verify frame timing is appropriate (100-200ms typical)
2. Export GIF with loop: true
3. Scale to 2x or 4x for visibility
4. Check file size (optimize if >2MB)
5. Suggest hosting platforms if needed
```
### Tileset for Game Engine
```
1. Verify tiles are uniform size (e.g., 16x16, 32x32)
2. Export as grid spritesheet
3. Set padding to 0 or 1 (depends on engine)
4. Include JSON for tile coordinates
5. Provide tile size and grid dimensions
```
## Game Engine Integration
### Unity Integration
**Export Settings:**
- Layout: "grid"
- Include JSON: true
- Padding: 1-2 pixels (prevents bleeding)
- Scale: 1x (Unity handles scaling)
**Import Steps:**
1. Import spritesheet.png into Assets
2. Set Texture Type to "Sprite (2D and UI)"
3. Set Sprite Mode to "Multiple"
4. Open Sprite Editor and use JSON coordinates to slice
5. Create Animator Controller with sprite animation
**Code Example:**
```csharp
SpriteRenderer renderer = GetComponent<SpriteRenderer>();
renderer.sprite = sprites[frameIndex];
```
### Godot Integration
**Export Settings:**
- Layout: "horizontal" or "grid"
- Include JSON: true
- Scale: 1x
- Padding: 0-1 pixels
**Import Steps:**
1. Import spritesheet.png to project
2. Create AnimatedSprite node
3. Create SpriteFrames resource
4. Add frames from spritesheet
5. Use JSON durations to set FPS
**Code Example:**
```gdscript
$AnimatedSprite.play("run")
$AnimatedSprite.speed_scale = 1.0
```
### Phaser Integration
**Export Settings:**
- Layout: "packed" or "horizontal"
- Include JSON: true (Texture Packer format)
- Scale: 1x or 2x depending on game resolution
**Import Steps:**
1. Place spritesheet.png and .json in assets
2. Load as atlas in preload()
3. Create sprite with atlas key
4. Create animations from frame names
**Code Example:**
```javascript
this.load.atlas('player', 'spritesheet.png', 'spritesheet.json');
this.anims.create({
key: 'run',
frames: this.anims.generateFrameNames('player', {
prefix: 'frame_',
suffix: '.png',
start: 0,
end: 7
}),
frameRate: 10,
repeat: -1
});
```
### Generic/Custom Engine
**Export Settings:**
- Layout: Based on engine capabilities
- Include JSON: true
- Provide simple frame array format
**JSON Structure:**
```json
{
"frames": [
{"x": 0, "y": 0, "w": 32, "h": 32, "duration": 100}
],
"meta": {
"frameWidth": 32,
"frameHeight": 32,
"frameCount": 8
}
}
```
**Integration Pattern:**
1. Load PNG texture
2. Parse JSON to get frame rectangles
3. Create sub-textures/sprites from coordinates
4. Use duration for animation timing
## Technical Details
### PNG Export Format
**Specifications:**
- Color Mode: RGBA (8-bit per channel)
- Transparency: Full alpha channel support
- Compression: PNG lossless compression
- Color Space: sRGB
- Bit Depth: 32-bit (8-bit per channel RGBA)
**When to Use:**
- Static sprites with transparency
- Individual frames from animations
- High-quality source files
- Layer-specific exports
### GIF Export Format
**Specifications:**
- Color Palette: Maximum 256 colors
- Transparency: Binary (on/off), no partial alpha
- Animation: Frame-based with per-frame timing
- Loop Control: Infinite or play-once
- Compression: LZW compression
**Limitations:**
- Color limit may require palette optimization
- No partial transparency (alpha is binary)
- Larger file sizes than video formats
- Limited to 8-bit color depth
**When to Use:**
- Web animations without video player
- Social media posts
- Email-compatible animations
- Simple looping animations
### Spritesheet Layouts
**Horizontal Layout:**
```
[Frame0][Frame1][Frame2][Frame3]...
```
- Dimensions: width = frameWidth * frameCount, height = frameHeight
- Best for: CSS animations, simple scrolling
**Vertical Layout:**
```
[Frame0]
[Frame1]
[Frame2]
[Frame3]
...
```
- Dimensions: width = frameWidth, height = frameHeight * frameCount
- Best for: Mobile-optimized, vertical scrolling
**Grid Layout:**
```
[Frame0][Frame1][Frame2][Frame3]
[Frame4][Frame5][Frame6][Frame7]
[Frame8][Frame9][Frame10][Frame11]
```
- Dimensions: Balanced to create near-square texture
- Best for: Game engines, power-of-2 textures, Unity, Godot
**Packed Layout:**
```
[Frame0][Frame2][Frame5]
[Frame1][Frame3][Frame6]
[Frame4][Frame7]
```
- Dimensions: Optimally packed to minimize wasted space
- Best for: Advanced engines with atlas support (Phaser, LibGDX)
- Requires JSON metadata for frame positions
### Metadata Structures
**Standard Frame Format:**
```json
{
"filename": "frame_0.png",
"frame": {"x": 0, "y": 0, "w": 32, "h": 32},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x": 0, "y": 0, "w": 32, "h": 32},
"sourceSize": {"w": 32, "h": 32},
"duration": 100
}
```
**Fields Explained:**
- `filename`: Logical frame identifier
- `frame`: Position and size in spritesheet (pixels)
- `rotated`: Whether frame is rotated 90° (packed layouts)
- `trimmed`: Whether transparent pixels were removed
- `spriteSourceSize`: Position within original canvas if trimmed
- `sourceSize`: Original canvas size before trimming
- `duration`: Frame duration in milliseconds
**Meta Information:**
```json
{
"app": "Aseprite",
"version": "1.3.x",
"format": "RGBA8888",
"size": {"w": 256, "h": 128},
"scale": "1",
"frameTags": [
{"name": "idle", "from": 0, "to": 3, "direction": "forward"},
{"name": "run", "from": 4, "to": 11, "direction": "forward"}
]
}
```
## Common Export Patterns
### Pattern 1: Single Frame Export
**Scenario:** User wants just one frame as PNG
```
1. mcp__aseprite__get_sprite_info (verify frame exists)
2. mcp__aseprite__export_png:
- file_path: "/output/frame.png"
- frame_number: 0 (or user-specified)
- scale: 1 (or user-specified)
3. Confirm export with dimensions
```
### Pattern 2: Full Animation GIF
**Scenario:** User wants animated GIF of entire sprite
```
1. mcp__aseprite__get_sprite_info (verify frames > 1)
2. mcp__aseprite__export_gif:
- file_path: "/output/animation.gif"
- loop: true
- scale: 2
3. Report frame count and file size
```
### Pattern 3: Game-Ready Spritesheet
**Scenario:** User wants spritesheet for Unity/Godot
```
1. mcp__aseprite__get_sprite_info (check dimensions and frames)
2. Ask about target engine if not specified
3. mcp__aseprite__export_spritesheet:
- file_path: "/output/spritesheet.png"
- layout: "grid"
- include_json: true
- padding: 1
- scale: 1
4. Provide integration instructions for target engine
```
### Pattern 4: Specific Animation Tag
**Scenario:** User wants to export just one animation (e.g., "run")
```
1. mcp__aseprite__get_sprite_info (verify tag exists)
2. mcp__aseprite__export_spritesheet or export_gif:
- animation_tag: "run"
- Other settings as appropriate
3. Confirm only tagged frames exported
```
### Pattern 5: Multi-Resolution Export
**Scenario:** User wants multiple scales (1x, 2x, 4x)
```
1. Export PNG/spritesheet at scale: 1
2. Export PNG/spritesheet at scale: 2
3. Export PNG/spritesheet at scale: 4
4. Organize files: sprite_1x.png, sprite_2x.png, sprite_4x.png
5. Report all outputs with dimensions
```
### Pattern 6: Layer-Specific Export
**Scenario:** User wants individual layers as separate files
```
1. mcp__aseprite__get_sprite_info (get layer names)
2. For each layer:
- mcp__aseprite__export_png:
- layer: "LayerName"
- file_path: "/output/layerName.png"
3. Report all exported layers
```
## Integration with Other Skills
### Pixel Art Creator Integration
**Workflow:** Create → Export
```
1. User creates sprite with Pixel Art Creator Skill
2. Automatically offer export options when creation complete
3. Suggest appropriate format based on sprite type (static vs animated)
4. Use this Skill to handle export
```
### Pixel Art Animator Integration
**Workflow:** Animate → Export
```
1. User creates animation with Pixel Art Animator Skill
2. When animation complete, offer export formats:
- GIF for web/social
- Spritesheet for games
3. Use this Skill for export with animation metadata
```
### Pixel Art Professional Integration
**Workflow:** Optimize → Export
```
1. User applies professional techniques (dithering, palette optimization)
2. Export with optimized settings:
- Preserve palette for GIF export
- Use appropriate compression for PNG
3. This Skill handles format-specific optimization
```
## Error Handling
### File Path Issues
**Problem:** Invalid or inaccessible output path
**Solution:**
```
1. Verify directory exists (create if needed using Bash)
2. Check write permissions
3. Use absolute paths, not relative
4. Suggest valid path if user provides invalid one
```
### Missing Frames or Tags
**Problem:** User requests frame/tag that doesn't exist
**Solution:**
```
1. Use get_sprite_info to verify available frames and tags
2. List available options to user
3. Ask user to clarify which frame/tag they want
4. Don't attempt export until valid selection made
```
### Large File Warnings
**Problem:** Export will create very large file (GIF >5MB, PNG >10MB)
**Solution:**
```
1. Calculate approximate size based on dimensions and frame count
2. Warn user before export if size exceeds thresholds
3. Suggest alternatives:
- Reduce scale factor
- Export fewer frames
- Use spritesheet instead of GIF
- Optimize palette
```
### Format Limitations
**Problem:** User requests feature not supported by format (e.g., GIF transparency)
**Solution:**
```
1. Explain format limitation clearly
2. Suggest alternative format or approach
3. Proceed with export noting the limitation
4. Examples:
- GIF binary transparency → suggest PNG for partial alpha
- GIF 256-color limit → suggest palette optimization first
```
### Scale Factor Issues
**Problem:** Non-integer scale or excessive scaling
**Solution:**
```
1. Only accept integer scale factors (1, 2, 3, 4, etc.)
2. Warn if scale >4 (may create very large files)
3. Explain pixel-perfect scaling benefits
4. Suggest appropriate scale for user's use case
```
## Success Indicators
**Export completed successfully when:**
1. **File Created**: Output file exists at specified path
2. **Correct Format**: File extension matches requested format (.png, .gif)
3. **Expected Dimensions**: Scaled dimensions are correct (originalSize * scale)
4. **Frame Count Match**: Spritesheet or GIF contains expected number of frames
5. **JSON Generated**: Metadata file created if include_json was true
6. **User Confirmation**: User can open and verify exported file
**Report to User:**
```
✓ Export complete: /path/to/output.png
- Format: PNG with transparency
- Dimensions: 64x64 (2x scale from 32x32 original)
- Frames: 1 (static image)
- File size: ~8KB
[For spritesheets, also include:]
- Layout: Grid (4x2)
- Frame dimensions: 32x32 each
- Total frames: 8
- JSON metadata: /path/to/output.json
- Integration: Ready for Unity/Godot import
[Provide relevant integration code snippet if applicable]
```
**Post-Export Guidance:**
- Suggest next steps (import to engine, optimize file size, create additional scales)
- Offer integration code for target platform
- Explain how to use JSON metadata
- Recommend testing in target environment

View File

@@ -0,0 +1,617 @@
# Pixel Art Exporter Examples
This document provides concrete examples of how the pixel-art-exporter skill handles exporting pixel art from Aseprite to various formats. Each example shows the user's request, step-by-step approach, actual MCP tool calls with parameters, and expected results.
Examples are organized by export type: single images, animated GIFs, spritesheets, and game engine integration workflows.
---
## Single Image Exports
### Example 1: Simple PNG Export
**User Request:**
> "Export my sprite as a PNG file with transparency"
**Approach:**
1. Get current sprite information
2. Export as PNG with alpha channel
3. Specify output path
4. Maintain original dimensions
**Tool Calls:**
```javascript
// Get sprite info to confirm dimensions
mcp__aseprite__get_sprite_info()
// Export as PNG with transparency
mcp__aseprite__export_png({
filename: "character-sprite.png",
frame: "current", // Export currently selected frame
layer: "all", // Include all layers
alpha: true // Preserve transparency
})
```
**Result:**
A PNG file with transparent background, ready to use in games or websites.
**Visual Description:**
The exported PNG shows the sprite with a checkered transparency background in image viewers. All colors are preserved exactly as they appear in Aseprite. The file can be placed over any background in a game engine or graphics program.
---
### Example 2: PNG with Specific Background Color
**User Request:**
> "Export my icon with a white background instead of transparency"
**Approach:**
1. Check sprite info
2. Export PNG with background color specified
3. Flatten transparency to solid color
**Tool Calls:**
```javascript
mcp__aseprite__get_sprite_info()
// Export PNG with white background
mcp__aseprite__export_png({
filename: "icon-white-bg.png",
frame: "current",
layer: "all",
alpha: false, // No transparency
background: { r: 255, g: 255, b: 255, a: 255 } // White
})
```
**Result:**
A PNG with white background replacing all transparent areas.
**Visual Description:**
The exported image has a solid white background. All transparent pixels have been filled with white. This is useful for icons that will be displayed on light backgrounds or for printing.
---
### Example 3: Scaled Export for High-DPI Displays
**User Request:**
> "Export my 32x32 sprite at 4x scale for retina displays, without blur"
**Approach:**
1. Get original dimensions
2. Export with integer scaling (nearest neighbor)
3. Maintain pixel-perfect sharpness
4. Output at 128x128 pixels
**Tool Calls:**
```javascript
// Get sprite info
const spriteInfo = mcp__aseprite__get_sprite_info()
// Returns: { width: 32, height: 32, colorMode: "rgb", frames: 1 }
// Export at 4x scale with nearest neighbor
mcp__aseprite__export_png({
filename: "character-4x.png",
frame: "current",
layer: "all",
alpha: true,
scale: 4, // 4x larger
scaleFilter: "nearest" // Pixel-perfect scaling (no blur)
})
```
**Result:**
A 128x128 PNG that looks identical to the original but 4x larger, with crisp pixel edges.
**Visual Description:**
The exported sprite is now 128x128 pixels. Each original pixel has become a 4x4 block of identical pixels. The image looks sharp and clear at large sizes with no blur or antialiasing artifacts. Perfect for high-DPI displays or large game sprites.
---
### Example 4: Export Specific Layer Only
**User Request:**
> "Export just the 'character' layer without the background"
**Approach:**
1. Identify layer name
2. Export only that layer
3. Maintain transparency from other layers
**Tool Calls:**
```javascript
// Get sprite info including layer information
mcp__aseprite__get_sprite_info()
// Export only the character layer
mcp__aseprite__export_png({
filename: "character-only.png",
frame: "current",
layer: "character", // Specific layer name
alpha: true
})
```
**Result:**
A PNG containing only the character layer, with background layer excluded and transparent.
**Visual Description:**
The exported image shows only the character sprite without the background elements. Areas where the background layer was are now fully transparent. Useful for exporting game assets separately or creating variations.
---
## Animated GIF Exports
### Example 5: Basic Animated GIF
**User Request:**
> "Export my walk cycle animation as an animated GIF"
**Approach:**
1. Verify animation has multiple frames
2. Export all frames as GIF
3. Use frame durations from Aseprite
4. Enable looping
**Tool Calls:**
```javascript
// Get sprite info to check frames
const spriteInfo = mcp__aseprite__get_sprite_info()
// Returns: { width: 32, height: 32, frames: 4, ... }
// Export as animated GIF
mcp__aseprite__export_gif({
filename: "walk-cycle.gif",
fromFrame: 1,
toFrame: 4, // All frames
loop: true, // Infinite loop
useOriginalDuration: true // Use Aseprite frame timings
})
```
**Result:**
An animated GIF that plays the walk cycle continuously, preserving the timing from Aseprite.
**Visual Description:**
The GIF animates smoothly, cycling through all 4 walk frames indefinitely. Frame timings match what was set in Aseprite (e.g., 100ms per frame). The animation looks exactly as it did in the Aseprite editor.
---
### Example 6: Optimized GIF with Reduced Colors
**User Request:**
> "Export my animation as a small GIF file with reduced file size"
**Approach:**
1. Get animation info
2. Export with palette optimization
3. Reduce color count for smaller file
4. Maintain visual quality
**Tool Calls:**
```javascript
mcp__aseprite__get_sprite_info()
// Export GIF with optimized palette
mcp__aseprite__export_gif({
filename: "optimized-animation.gif",
fromFrame: 1,
toFrame: 8,
loop: true,
useOriginalDuration: true,
colorQuantization: true, // Optimize palette
maxColors: 64, // Reduce from 256 to 64 colors
dithering: "floyd-steinberg" // Smooth color transitions
})
```
**Result:**
A smaller GIF file with optimized colors that looks nearly identical to the full-color version.
**Visual Description:**
The GIF plays the animation smoothly with slightly reduced color depth. Floyd-Steinberg dithering creates smooth transitions where colors were reduced. File size is significantly smaller (often 50-70% reduction) while maintaining good visual quality.
---
### Example 7: GIF with Specific Frame Range
**User Request:**
> "Export just frames 5-8 of my animation (the attack sequence) as a GIF"
**Approach:**
1. Identify frame range for specific animation
2. Export only that range
3. Set appropriate loop behavior
**Tool Calls:**
```javascript
mcp__aseprite__get_sprite_info()
// Export specific frame range
mcp__aseprite__export_gif({
filename: "attack-animation.gif",
fromFrame: 5,
toFrame: 8, // Just the attack frames
loop: false, // Play once (not infinite loop)
useOriginalDuration: true
})
```
**Result:**
A GIF containing only the 4-frame attack sequence that plays once and stops.
**Visual Description:**
The GIF shows frames 5-8 of the original animation (the attack move). It plays through once and stops on the last frame rather than looping. Perfect for sharing a specific animation sequence or game move demonstrations.
---
## Spritesheet Exports
### Example 8: Horizontal Strip Spritesheet
**User Request:**
> "Export all my animation frames as a single horizontal strip for my game engine"
**Approach:**
1. Get frame count
2. Export as horizontal spritesheet
3. Frames arranged left to right
4. Include metadata about frame positions
**Tool Calls:**
```javascript
// Get sprite info
const spriteInfo = mcp__aseprite__get_sprite_info()
// Returns: { width: 32, height: 32, frames: 8, ... }
// Export as horizontal strip
mcp__aseprite__export_spritesheet({
filename: "spritesheet-horizontal.png",
sheetType: "horizontal", // All frames in one row
fromFrame: 1,
toFrame: 8,
padding: 0, // No space between frames
innerPadding: 0 // No padding inside frames
})
```
**Result:**
A 256x32 PNG (8 frames × 32px wide) with all frames arranged horizontally.
**Visual Description:**
The spritesheet is a wide horizontal image showing all 8 animation frames side by side. Frame 1 starts at x=0, frame 2 at x=32, frame 3 at x=64, and so on. Each frame is 32x32 pixels. The spritesheet is 256 pixels wide by 32 pixels tall.
---
### Example 9: Grid Spritesheet with JSON Data
**User Request:**
> "Export my sprites as a grid spritesheet with JSON metadata for frame positions"
**Approach:**
1. Arrange frames in a grid (e.g., 4x2)
2. Export PNG spritesheet
3. Export accompanying JSON with frame coordinates
4. Include frame durations
**Tool Calls:**
```javascript
// Get sprite info
const spriteInfo = mcp__aseprite__get_sprite_info()
// Export as grid with JSON
mcp__aseprite__export_spritesheet({
filename: "spritesheet-grid.png",
sheetType: "grid",
columns: 4, // 4 frames per row
rows: 2, // 2 rows
fromFrame: 1,
toFrame: 8,
padding: 1, // 1px space between frames
innerPadding: 0,
jsonData: true, // Export JSON metadata
jsonFilename: "spritesheet-grid.json"
})
```
**Result:**
A 133x65 PNG grid (4×2 frames with padding) plus a JSON file with frame coordinates and timing data.
**Visual Description:**
The spritesheet shows 8 frames arranged in a 4×2 grid. Each frame is separated by 1 pixel of padding. The accompanying JSON file contains:
```json
{
"frames": [
{
"frame": { "x": 0, "y": 0, "w": 32, "h": 32 },
"duration": 100
},
{
"frame": { "x": 33, "y": 0, "w": 32, "h": 32 },
"duration": 100
},
// ... more frames
],
"meta": {
"size": { "w": 133, "h": 65 },
"scale": "1"
}
}
```
---
### Example 10: Packed Spritesheet for Efficiency
**User Request:**
> "Export my sprites as a tightly packed spritesheet to save texture memory"
**Approach:**
1. Analyze frame sizes
2. Use bin-packing algorithm
3. Arrange frames efficiently
4. Export with JSON coordinates
**Tool Calls:**
```javascript
// Export with automatic packing
mcp__aseprite__export_spritesheet({
filename: "spritesheet-packed.png",
sheetType: "packed", // Bin-packing algorithm
fromFrame: 1,
toFrame: 8,
padding: 2, // 2px padding for safety
powerOfTwo: true, // Force dimensions to power of 2
jsonData: true,
jsonFilename: "spritesheet-packed.json"
})
```
**Result:**
An efficiently packed spritesheet (e.g., 64x64 or 128x64) with frames arranged to minimize wasted space, plus JSON coordinates.
**Visual Description:**
The spritesheet uses minimal texture space by packing frames tightly. Frames aren't in a regular grid - they're arranged optimally based on size and shape. The JSON file provides exact coordinates for each frame. The total image size is a power of 2 (64x64, 128x128, etc.) for GPU efficiency.
---
### Example 11: Spritesheet with Animation Tags
**User Request:**
> "Export a spritesheet with separate animations (idle, walk, attack) marked in the JSON"
**Approach:**
1. Create spritesheet with all frames
2. Export JSON including animation tag ranges
3. Organize by animation name
**Tool Calls:**
```javascript
// Get sprite info including tags
const spriteInfo = mcp__aseprite__get_sprite_info()
// Returns: { frames: 16, tags: ["idle", "walk", "attack"], ... }
// Export spritesheet with tag information
mcp__aseprite__export_spritesheet({
filename: "character-all-animations.png",
sheetType: "horizontal",
fromFrame: 1,
toFrame: 16, // All frames
padding: 1,
jsonData: true,
jsonFilename: "character-all-animations.json",
includeTags: true // Include animation tag data in JSON
})
```
**Result:**
A horizontal spritesheet with all 16 frames plus JSON with animation tag ranges.
**Visual Description:**
The spritesheet contains all animations in sequence: idle (frames 1-4), walk (frames 5-8), attack (frames 9-16). The JSON includes:
```json
{
"frames": [ /* frame data */ ],
"meta": {
"frameTags": [
{ "name": "idle", "from": 0, "to": 3 },
{ "name": "walk", "from": 4, "to": 7 },
{ "name": "attack", "from": 8, "to": 15 }
]
}
}
```
---
## Game Engine Integration
### Example 12: Unity Spritesheet Export
**User Request:**
> "Export my animation for Unity with the correct JSON format"
**Approach:**
1. Export spritesheet in Unity-compatible format
2. Use Unity's JSON structure
3. Include pivot points and frame data
**Tool Calls:**
```javascript
// Export Unity-compatible spritesheet
mcp__aseprite__export_spritesheet({
filename: "unity-sprite.png",
sheetType: "grid",
columns: 4,
rows: 2,
fromFrame: 1,
toFrame: 8,
padding: 0,
jsonData: true,
jsonFilename: "unity-sprite.json",
jsonFormat: "unity" // Unity-specific format
})
```
**Result:**
A spritesheet PNG and JSON in Unity's sprite atlas format.
**Visual Description:**
The export creates files that Unity can import directly. The JSON uses Unity's expected structure with sprite names, rectangles, pivots, and borders. In Unity, you can drag the PNG into your project, set it as Multiple sprite mode, and use the JSON to slice it automatically.
---
### Example 13: Godot Spritesheet Export
**User Request:**
> "Export my sprites for Godot Engine with proper metadata"
**Approach:**
1. Export spritesheet
2. Use Godot-compatible JSON format
3. Include region and frame data
**Tool Calls:**
```javascript
// Export Godot-compatible spritesheet
mcp__aseprite__export_spritesheet({
filename: "godot-sprite.png",
sheetType: "packed",
fromFrame: 1,
toFrame: 8,
padding: 1,
jsonData: true,
jsonFilename: "godot-sprite.json",
jsonFormat: "godot" // Godot-specific format
})
```
**Result:**
A packed spritesheet with Godot-compatible JSON metadata.
**Visual Description:**
The export creates files ready for Godot's AnimatedSprite or SpriteFrames resource. The JSON uses Godot's expected structure. In Godot, you can load this directly into a SpriteFrames resource and reference frames by name in your animations.
---
### Example 14: Phaser JSON Hash Export
**User Request:**
> "Export my spritesheet with Phaser 3 compatible JSON hash format"
**Approach:**
1. Export spritesheet
2. Use Phaser's JSON hash structure
3. Include all frame data with string keys
**Tool Calls:**
```javascript
// Export Phaser-compatible spritesheet
mcp__aseprite__export_spritesheet({
filename: "phaser-sprite.png",
sheetType: "grid",
columns: 4,
rows: 2,
fromFrame: 1,
toFrame: 8,
padding: 0,
jsonData: true,
jsonFilename: "phaser-sprite.json",
jsonFormat: "hash" // Phaser JSON hash format
})
```
**Result:**
A spritesheet with Phaser 3 JSON hash format for easy loading.
**Visual Description:**
The JSON uses Phaser's hash format where each frame is a key-value pair:
```json
{
"frames": {
"frame0.png": {
"frame": { "x": 0, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 }
},
// ... more frames
}
}
```
In Phaser, load with: `this.load.atlas('sprite', 'phaser-sprite.png', 'phaser-sprite.json')`
---
### Example 15: Export Multiple Animations Separately
**User Request:**
> "Export each of my tagged animations as separate files for easier game engine management"
**Approach:**
1. Get list of animation tags
2. Export each tag as separate file
3. Create organized file structure
**Tool Calls:**
```javascript
// Get sprite info with tags
const spriteInfo = mcp__aseprite__get_sprite_info()
// Returns: { tags: ["idle", "walk", "attack"], ... }
// Export idle animation
mcp__aseprite__export_spritesheet({
filename: "character-idle.png",
sheetType: "horizontal",
tag: "idle", // Export only frames in this tag
padding: 0,
jsonData: true,
jsonFilename: "character-idle.json"
})
// Export walk animation
mcp__aseprite__export_spritesheet({
filename: "character-walk.png",
sheetType: "horizontal",
tag: "walk", // Export only frames in this tag
padding: 0,
jsonData: true,
jsonFilename: "character-walk.json"
})
// Export attack animation
mcp__aseprite__export_spritesheet({
filename: "character-attack.png",
sheetType: "horizontal",
tag: "attack", // Export only frames in this tag
padding: 0,
jsonData: true,
jsonFilename: "character-attack.json"
})
```
**Result:**
Three separate spritesheet files, each containing one animation with its own JSON.
**Visual Description:**
The export creates:
- `character-idle.png`: 128x32 (4 frames)
- `character-walk.png`: 128x32 (4 frames)
- `character-attack.png`: 192x32 (6 frames)
Plus corresponding JSON files. This organization makes it easy to load only needed animations in game engines and manage animation states separately.
---
## Summary
This examples collection demonstrates the pixel-art-exporter skill's capabilities:
- **Single images** (Examples 1-4): PNG exports with various options (transparency, backgrounds, scaling, layers)
- **Animated GIFs** (Examples 5-7): Full animations, optimized versions, specific frame ranges
- **Spritesheets** (Examples 8-11): Horizontal strips, grids, packed layouts, with JSON metadata
- **Game engine integration** (Examples 12-15): Unity, Godot, Phaser formats, and organized multi-file exports
Each example shows complete MCP tool call syntax with practical export scenarios for web, games, and various platforms. The progression demonstrates flexibility from simple PNG exports to complex multi-format game engine pipelines.

View File

@@ -0,0 +1,823 @@
# Export Formats Reference
This document provides comprehensive technical specifications for exporting pixel art in various formats, including static images, animated formats, spritesheets, and game engine-specific outputs.
## PNG Export Options
PNG (Portable Network Graphics) is the primary format for pixel art due to lossless compression and transparency support.
### Transparency Handling
**Full Alpha Channel:**
- 8-bit alpha channel (0-255 transparency levels)
- Preserves semi-transparent pixels from antialiasing or effects
- Essential for overlay sprites, particles, or UI elements
- File size increases with alpha complexity
**Binary Transparency:**
- Pixels are either fully opaque (255) or fully transparent (0)
- Smaller file size compared to full alpha
- Sufficient for most pixel art with hard edges
- Compatible with older systems
**No Transparency:**
- All pixels opaque
- Smallest file size for PNG
- Use when background is always solid
- Useful for tiles, backgrounds, or when transparency not needed
### Background Colors
**Transparent Background:**
- Default for sprites, characters, UI elements
- Allows compositing over any background
- Required for multi-layer game objects
**Solid Background:**
- Specify hex color (e.g., #FF00FF for magenta)
- Useful for preview/reference images
- Can use specific color for manual masking later
- Common for texture atlases with padding
**Checkerboard Pattern:**
- Not exported, but visible in editor
- Indicates transparent areas during editing
- Final export still uses true transparency
### Color Depth Options
**Indexed Color (8-bit):**
- Maximum 256 colors
- Smallest file size
- Perfect for retro pixel art
- Preserves exact palette
- Example: NES-style art (54 colors), Game Boy (4 colors)
**RGB (24-bit):**
- 16.7 million colors
- No transparency channel
- Use when alpha not needed
- Moderate file size
**RGBA (32-bit):**
- 16.7 million colors + alpha
- Full transparency support
- Largest file size
- Industry standard for modern games
### Compression Settings
**PNG Compression Levels:**
- Level 0: No compression (fastest, largest)
- Level 1-5: Low compression (fast encoding)
- Level 6: Default (balanced)
- Level 9: Maximum compression (slowest, smallest)
**Best Practices:**
- Use level 9 for final game assets (one-time cost)
- Use level 1-3 for rapid iteration/testing
- Compression is lossless at all levels
- File size varies by image complexity, not canvas size
## GIF Export
GIF format provides animation support with wide compatibility but limited color palette.
### Frame Timing Control
**Frame Duration:**
- Measured in centiseconds (100ths of a second)
- Minimum: 1cs (10ms) - browser limit typically 20ms
- Common values: 10cs (100ms), 5cs (50ms), 20cs (200ms)
- Per-frame timing allows variable animation speeds
**Timing Examples:**
```
Walking cycle: 10cs per frame (10 FPS)
Idle breathing: 30cs per frame (3.3 FPS)
Fast attack: 5cs per frame (20 FPS)
Slow blink: [50cs, 5cs, 50cs] (hold, blink, hold)
```
**Aseprite Frame Duration:**
- Set in timeline (milliseconds in Aseprite)
- Export converts to centiseconds
- Maintains exact timing in GIF output
### Looping Options
**Infinite Loop:**
- Default for game sprites
- NETSCAPE2.0 extension with loop count 0
- Plays continuously until stopped
- Standard for web animations
**Count-Based Looping:**
- Specify exact number of repetitions
- Example: Loop 3 times then stop
- Useful for intro animations, effects
- Browser support varies
**No Loop (Play Once):**
- Loop count set to 1
- Stops on final frame
- Good for cutscenes, transitions
- Fallback: some viewers may still loop
### Color Quantization for GIF
**256 Color Limitation:**
- GIF maximum palette size
- Quantization reduces full-color to 256 colors
- Critical consideration when exporting from 24-bit source
**Quantization Algorithms:**
**Global Palette:**
- Single 256-color palette for all frames
- Ensures color consistency across animation
- Analyze all frames to build optimal palette
- Best for most pixel art animations
**Local Palette:**
- Different palette per frame
- Allows more colors across animation
- Can cause color shifting/flickering
- Rarely appropriate for pixel art
**Dithering Options:**
- **None**: Hard color boundaries (best for pixel art)
- **Floyd-Steinberg**: Error diffusion, adds noise
- **Ordered**: Pattern-based, creates artifacts
- **Recommendation**: Disable dithering for pixel art
### Optimization Techniques
**Frame Disposal Methods:**
- **Restore to Background**: Clear before next frame
- **Do Not Dispose**: Keep previous frame
- **Restore to Previous**: Revert to prior state
**Delta Frame Encoding:**
- Only encode changed pixels between frames
- Significant size reduction for small changes
- Automatic in most GIF encoders
- Example: Idle animation (80% size reduction)
**Transparency Optimization:**
- Designate one color as transparent
- Reduce file size by not encoding unchanged areas
- Works with delta encoding
- Choose unused color for transparency index
**Size Reduction Checklist:**
- Use global palette
- Enable delta encoding
- Minimize frame dimensions (crop to animation bounds)
- Reduce frame count if possible
- Lower frame rate for slower animations
### File Size Considerations
**Size Factors:**
```
Small (1-50 KB): 16×16 sprite, 4-8 frames, simple movement
Medium (50-200 KB): 32×32 sprite, 10-20 frames, detailed animation
Large (200KB-1MB): 64×64+ sprite, 30+ frames, complex animation
```
**Optimization Trade-offs:**
- Frame count vs. smoothness
- Canvas size vs. detail
- Frame rate vs. file size
- Color count vs. palette accuracy
## Spritesheet Layouts
Spritesheets combine multiple frames or sprites into a single image for efficient loading and rendering.
### Horizontal Strip
All frames arranged in a single horizontal row.
```
+----+----+----+----+----+
| F1 | F2 | F3 | F4 | F5 |
+----+----+----+----+----+
```
**Use Cases:**
- Simple animations (walk, run, jump)
- Scrolling backgrounds
- UI button states
**Advantages:**
- Simple to parse (X offset only)
- Easy to calculate frame position: `frame_x = frame_index * frame_width`
- Good for texture atlases with power-of-2 heights
**Disadvantages:**
- Very wide images with many frames
- Inefficient for non-power-of-2 widths
- GPU texture size limits (typically 4096-8192px)
### Vertical Strip
All frames arranged in a single vertical column.
```
+----+
| F1 |
+----+
| F2 |
+----+
| F3 |
+----+
| F4 |
+----+
```
**Use Cases:**
- Mobile-optimized layouts
- Vertical scrolling effects
- Legacy systems preferring tall textures
**Advantages:**
- Simple to parse (Y offset only)
- Frame position: `frame_y = frame_index * frame_height`
- Better for portrait-oriented displays
**Disadvantages:**
- Very tall images
- Less common than horizontal
- Same texture size constraints
### Grid Layout
Frames arranged in rows and columns.
```
+----+----+----+----+
| F1 | F2 | F3 | F4 |
+----+----+----+----+
| F5 | F6 | F7 | F8 |
+----+----+----+----+
| F9 | 10 | 11 | 12 |
+----+----+----+----+
```
**Configuration:**
- Rows: Number of vertical divisions
- Columns: Number of horizontal divisions
- Example: 4 columns × 3 rows = 12 frames
**Frame Calculation:**
```python
frame_x = (frame_index % columns) * frame_width
frame_y = (frame_index // columns) * frame_height
```
**Use Cases:**
- Large animation sets (16+ frames)
- Multiple animations in one sheet
- Power-of-2 texture optimization
**Advantages:**
- Balanced dimensions (square or near-square)
- GPU-friendly (easier to fit power-of-2)
- Compact representation
**Best Practices:**
- Use power-of-2 dimensions: 256×256, 512×512, 1024×1024
- Add padding between frames (1-2px) to prevent bleeding
- Organize by animation (row per animation type)
### Packed Layout
Optimal space usage with variable frame positions.
```
+--------+----+----+
| | F3 | F4 |
| F1 +----+----+
| | F5 | F6 |
+----+---+----+----+
| F2 | F7 | F8|
+----+---------+---+
```
**Characteristics:**
- Frames positioned to minimize whitespace
- Requires metadata for frame positions
- Non-uniform layout
**Algorithms:**
- **Maxrects**: Maximum rectangles bin packing
- **Skyline**: Skyline bottom-left heuristic
- **Guillotine**: Recursive subdivision
**Use Cases:**
- Variable-size sprites (UI elements, items)
- Texture atlases with many assets
- Maximizing GPU texture memory
**Advantages:**
- Smallest total texture size
- Efficient memory usage
- Professional game asset pipelines
**Disadvantages:**
- Requires JSON/XML metadata
- More complex to parse
- Not suitable for uniform animations
**Metadata Example:**
```json
{
"frame1": {"x": 0, "y": 0, "w": 32, "h": 64},
"frame2": {"x": 0, "y": 64, "w": 16, "h": 16},
"frame3": {"x": 32, "y": 0, "w": 16, "h": 16}
}
```
## JSON Metadata Formats
JSON files provide frame data, animation metadata, and asset information for game engines.
### Aseprite JSON Format
Native format exported by Aseprite with comprehensive metadata.
```json
{
"frames": {
"sprite_0.aseprite": {
"frame": {"x": 0, "y": 0, "w": 32, "h": 32},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x": 0, "y": 0, "w": 32, "h": 32},
"sourceSize": {"w": 32, "h": 32},
"duration": 100
},
"sprite_1.aseprite": {
"frame": {"x": 32, "y": 0, "w": 32, "h": 32},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x": 0, "y": 0, "w": 32, "h": 32},
"sourceSize": {"w": 32, "h": 32},
"duration": 100
}
},
"meta": {
"app": "http://www.aseprite.org/",
"version": "1.3.0",
"image": "sprite.png",
"format": "RGBA8888",
"size": {"w": 128, "h": 32},
"scale": "1",
"frameTags": [
{
"name": "walk",
"from": 0,
"to": 3,
"direction": "forward"
}
],
"layers": [
{"name": "Layer 1", "opacity": 255, "blendMode": "normal"}
],
"slices": []
}
}
```
**Key Fields:**
- `frames`: Per-frame data with positions and durations
- `frameTags`: Animation sequences (walk, run, idle)
- `direction`: forward, reverse, pingpong
- `duration`: Frame duration in milliseconds
### TexturePacker JSON Format
Industry-standard format used by many tools and engines.
```json
{
"frames": {
"hero_walk_00.png": {
"frame": {"x": 2, "y": 2, "w": 32, "h": 32},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x": 2, "y": 1, "w": 32, "h": 32},
"sourceSize": {"w": 36, "h": 34},
"pivot": {"x": 0.5, "y": 0.5}
}
},
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "spritesheet.png",
"format": "RGBA8888",
"size": {"w": 512, "h": 512},
"scale": "1"
}
}
```
**Key Features:**
- `trimmed`: Indicates if transparent pixels were removed
- `spriteSourceSize`: Position of trimmed sprite in original
- `pivot`: Rotation/scaling origin point (0-1 normalized)
- Widely supported by game frameworks
### Unity Sprite Atlas Format
Unity-specific JSON structure for sprite atlases.
```json
{
"name": "PlayerAtlas",
"spriteSheet": {
"sprites": [
{
"name": "player_idle_0",
"rect": {"x": 0, "y": 0, "width": 32, "height": 32},
"pivot": {"x": 0.5, "y": 0},
"border": {"x": 0, "y": 0, "z": 0, "w": 0},
"alignment": 7,
"pixelsPerUnit": 32
},
{
"name": "player_idle_1",
"rect": {"x": 32, "y": 0, "width": 32, "height": 32},
"pivot": {"x": 0.5, "y": 0},
"border": {"x": 0, "y": 0, "z": 0, "w": 0},
"alignment": 7,
"pixelsPerUnit": 32
}
]
}
}
```
**Unity-Specific Fields:**
- `pixelsPerUnit`: Sprite resolution (typically 32 or 100)
- `alignment`: Pivot preset (7 = bottom-center)
- `border`: 9-slice borders for UI scaling
- Compatible with Unity's SpriteAtlas system
### Godot SpriteFrames Format
Godot engine's resource format for AnimatedSprite nodes.
```json
{
"frames": [
{
"name": "walk",
"frames": [
{"texture": "res://sprites/player_walk_0.png", "duration": 0.1},
{"texture": "res://sprites/player_walk_1.png", "duration": 0.1},
{"texture": "res://sprites/player_walk_2.png", "duration": 0.1},
{"texture": "res://sprites/player_walk_3.png", "duration": 0.1}
]
},
{
"name": "idle",
"frames": [
{"texture": "res://sprites/player_idle_0.png", "duration": 0.5},
{"texture": "res://sprites/player_idle_1.png", "duration": 0.5}
]
}
],
"speed": 10.0,
"loop": true
}
```
**Godot Features:**
- Animation-based organization (not single frames)
- Per-frame duration in seconds
- Global speed multiplier
- Directly compatible with AnimatedSprite node
## Scaling Considerations
Pixel art requires special handling when scaling to maintain crisp, pixel-perfect appearance.
### Nearest-Neighbor Algorithm
**How It Works:**
- Each output pixel uses value from closest input pixel
- No interpolation or blending
- Preserves hard edges and exact colors
**Mathematical Definition:**
```
output[x, y] = input[floor(x / scale), floor(y / scale)]
```
**Results:**
- Perfectly sharp pixels
- No color bleeding or artifacts
- Integer scales produce perfect results
- Non-integer scales may show uneven pixels
**Essential for Pixel Art:**
- Maintains artistic intent
- Preserves hand-placed pixels
- No blur or antialiasing
- Industry standard for retro aesthetics
### Why Other Algorithms Blur Pixels
**Bilinear Interpolation:**
- Averages 4 nearest pixels
- Creates smooth gradients
- **Problem**: Blurs pixel art edges
- Use case: Photography, 3D textures
**Bicubic Interpolation:**
- Averages 16 nearest pixels
- Even smoother than bilinear
- **Problem**: Severe blurring for pixel art
- Use case: High-quality photo scaling
**Lanczos Resampling:**
- Advanced algorithm, high quality
- **Problem**: Introduces ringing artifacts
- Use case: Photographic downscaling
**Visual Comparison:**
```
Original (8×8): Nearest (16×16): Bilinear (16×16):
████████ ████████████████ ░░░░░░░░░░░░░░░░
██ ██ ████ ████ ░░██ ██░░
██ ██ ------> ████ ████ ░░██ ██░░
████████ ████████████████ ░░░░░░░░░░░░░░░░
(Sharp edges) (Sharp edges) (Blurred edges)
```
### Common Scale Factors
**Integer Scales (Recommended):**
- **1x**: Native resolution (32×32 remains 32×32)
- **2x**: Double size (32×32 becomes 64×64)
- **4x**: Quad size (32×32 becomes 128×128)
- **8x**: Octo size (32×32 becomes 256×256)
**Benefits:**
- Perfect pixel mapping (1 source pixel → N×N output pixels)
- No distortion or uneven pixels
- Crisp, clean appearance
**Non-Integer Scales (Use with Caution):**
- **1.5x**: Some pixels larger than others
- **3x**: Still integer, good quality
- **2.5x**: Uneven pixel sizes, slight distortion
**Best Practices:**
- Prefer integer scales (2x, 3x, 4x)
- Design base sprites at smallest playable size
- Scale up for high-DPI displays
- Use viewport/camera scaling instead of asset scaling when possible
### Maintaining Pixel-Perfect Appearance
**Canvas Alignment:**
- Position sprites on integer coordinates
- Avoid sub-pixel positioning (0.5, 1.3, etc.)
- Round camera position to integers
**Viewport Scaling:**
- Scale entire game viewport, not individual sprites
- Maintain aspect ratio
- Use integer scale factors
**Export Settings:**
- Disable antialiasing
- Use nearest-neighbor filter
- Set texture filtering to "Point" or "Nearest"
**GPU Texture Settings:**
- Mag Filter: Nearest/Point
- Min Filter: Nearest/Point (not Mipmap)
- Wrap Mode: Clamp or Repeat as needed
## Game Engine Integration Examples
### Unity
**Import Settings:**
```
Texture Type: Sprite (2D and UI)
Sprite Mode: Multiple (for spritesheets)
Pixels Per Unit: 32 (or native sprite size)
Filter Mode: Point (no filter)
Compression: None
Format: RGBA 32 bit
```
**Sprite Atlas Usage:**
```csharp
using UnityEngine;
public class SpriteAnimator : MonoBehaviour
{
public Sprite[] walkFrames;
private SpriteRenderer spriteRenderer;
private int currentFrame = 0;
private float frameTimer = 0f;
private float frameDuration = 0.1f;
void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>();
}
void Update()
{
frameTimer += Time.deltaTime;
if (frameTimer >= frameDuration)
{
frameTimer = 0f;
currentFrame = (currentFrame + 1) % walkFrames.Length;
spriteRenderer.sprite = walkFrames[currentFrame];
}
}
}
```
### Godot
**SpriteFrames Setup:**
```gdscript
# Import spritesheet
var texture = preload("res://sprites/player.png")
# Create SpriteFrames resource
var sprite_frames = SpriteFrames.new()
# Add animation
sprite_frames.add_animation("walk")
sprite_frames.set_animation_speed("walk", 10.0)
# Add frames (assume 32×32 frames in horizontal strip)
for i in range(4):
var atlas = AtlasTexture.new()
atlas.atlas = texture
atlas.region = Rect2(i * 32, 0, 32, 32)
sprite_frames.add_frame("walk", atlas, i)
```
**AnimatedSprite Configuration:**
```gdscript
extends AnimatedSprite
func _ready():
# Disable filtering for pixel-perfect
texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
# Play animation
play("walk")
```
**Project Settings:**
```
Rendering > Textures > Canvas Textures > Default Texture Filter: Nearest
Display > Window > Stretch > Mode: viewport
Display > Window > Stretch > Aspect: keep
```
### Phaser
**Loading Spritesheet:**
```javascript
class GameScene extends Phaser.Scene {
preload() {
// Load spritesheet
this.load.spritesheet('player', 'assets/player.png', {
frameWidth: 32,
frameHeight: 32
});
}
create() {
// Create animation from frames 0-3
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNumbers('player', {
start: 0,
end: 3
}),
frameRate: 10,
repeat: -1
});
// Create sprite
const player = this.add.sprite(100, 100, 'player');
player.play('walk');
// Disable texture smoothing for pixel-perfect
player.setTexture('player').setOrigin(0.5, 0.5);
}
}
```
**Game Configuration:**
```javascript
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
pixelArt: true, // Enables nearest-neighbor filtering
render: {
antialias: false,
pixelArt: true
},
scene: [GameScene]
};
const game = new Phaser.Game(config);
```
### Generic Engine Patterns
**Frame-Based Animation Loop:**
```javascript
class Animation {
constructor(frames, frameDuration) {
this.frames = frames; // Array of frame data {x, y, w, h}
this.frameDuration = frameDuration; // Milliseconds per frame
this.currentFrame = 0;
this.elapsedTime = 0;
}
update(deltaTime) {
this.elapsedTime += deltaTime;
if (this.elapsedTime >= this.frameDuration) {
this.elapsedTime = 0;
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
}
}
getCurrentFrame() {
return this.frames[this.currentFrame];
}
}
```
**Spritesheet Rendering:**
```javascript
function drawSprite(context, image, frame, x, y, scale) {
// Use nearest-neighbor scaling
context.imageSmoothingEnabled = false;
context.drawImage(
image,
frame.x, frame.y, frame.w, frame.h, // Source
Math.floor(x), Math.floor(y), // Destination (integer coords)
frame.w * scale, frame.h * scale // Scaled size
);
}
```
**JSON Metadata Parsing:**
```javascript
async function loadSpritesheet(imagePath, jsonPath) {
const [image, metadata] = await Promise.all([
loadImage(imagePath),
fetch(jsonPath).then(r => r.json())
]);
const animations = {};
// Parse Aseprite JSON format
for (const tag of metadata.meta.frameTags) {
const frames = [];
for (let i = tag.from; i <= tag.to; i++) {
const frameKey = Object.keys(metadata.frames)[i];
const frameData = metadata.frames[frameKey];
frames.push({
x: frameData.frame.x,
y: frameData.frame.y,
w: frameData.frame.w,
h: frameData.frame.h,
duration: frameData.duration
});
}
animations[tag.name] = new Animation(frames, frames[0].duration);
}
return { image, animations };
}
```
**Best Practices Summary:**
- Always disable texture filtering (use nearest/point)
- Position sprites on integer pixel coordinates
- Use integer scale factors
- Set `imageSmoothingEnabled = false` for canvas
- Configure engine for pixel-perfect rendering
- Load metadata alongside spritesheet images
- Cache parsed animations for performance