Character Factory¶
Skill ID: ivx-character-factory
name: ivx-character-factory description: >- AI-powered 2D character generation for any game engine. Generates full sprite sheets, expression grids, emotional states, topic skins, and promo art — all validated against IntelliVerseX SDK schemas. Use when the user says "generate character", "create sprites", "character factory", "pixel art character", "expression sheet", "emotional states", "topic skins", "character variants", "AI character", "sprite generation", "generate game character", or needs AI-generated 2D game characters. version: "1.0.0" author: "IntelliVerse-X team@intelli-verse-x.ai" allowed-tools: - Read - Write - Edit - Glob - Grep - Shell
Overview¶
The Character Factory uses the Content-Factory AI pipeline to generate production-ready 2D game characters from text descriptions. Every output conforms to IntelliVerseX SDK schemas (character-meta-v1, sprite-spec-v1) and is directly importable into Unity, Unreal, Godot, Defold, Roblox, or any engine that reads sprite sheets.
Text Description
│
▼
┌── Content-Factory ──────────────────────────────┐
│ LLM prompt engineering → Fal Nano Banana Pro │
│ → Per-cell rembg (isnet-anime) → Alpha harden │
│ → IVX Schema Export → S3 Upload │
└──────────────────────┬──────────────────────────┘
│
▼
SDK-Valid Output
character.json (character-meta-v1)
sprites/*_spec.json (sprite-spec-v1)
sprites/*.png (horizontal strips)
expressions/expressions_front.png
views/front.png, thumbnail.png
Content-Factory API¶
Trigger via MCP¶
trigger_pipeline character_2d --game_id my-game --character "A brave robot named Bolt with glowing blue eyes, pixel art style"
Trigger via REST¶
curl -X POST http://localhost:8001/pipelines/character_2d \
-H "Content-Type: application/json" \
-d '{
"game_id": "my-game",
"characters": [
{
"name": "Bolt",
"description": "A brave robot with glowing blue eyes and a jetpack",
"style": "pixel_art"
}
],
"ivx_export": true
}'
Trigger via Python¶
from pipelines.animation.character_2d import Character2DAnimationPipeline
pipeline = Character2DAnimationPipeline()
result = await pipeline.run({
"game_id": "my-game",
"characters": [{"name": "Bolt", "description": "A brave robot..."}],
"style": "pixel_art",
"ivx_export": True,
})
Generated Output¶
Folder Structure¶
characters/Bolt/
├── sprites/
│ ├── idle.png # 6-frame horizontal strip (3072×512)
│ ├── walk.png # 6-frame strip
│ ├── run.png # 6-frame strip
│ ├── jump.png # 4-frame strip
│ ├── attack.png # 6-frame strip
│ ├── hurt.png # 3-frame strip
│ ├── death.png # 4-frame strip
│ └── cast.png # 5-frame strip
├── expressions/
│ └── expressions_front.png # 3×2 grid: neutral, happy, sad, angry, surprised, thinking
├── emotional_states/
│ ├── determined.png
│ ├── happy.png
│ ├── legendary.png
│ ├── proud.png
│ ├── sad.png
│ └── sleeping.png
├── promo/
│ ├── app_icon.png # 1:1
│ ├── thumbnail.png # 16:9
│ ├── key_art.png # 16:9
│ └── social_banner.png # 3:1
├── topic_skins/
│ ├── anime.png
│ ├── sport.png
│ └── holiday.png
└── ivx/ # SDK-compliant exports
├── character.json # Validates: character-meta-v1
├── sprites/
│ ├── idle_spec.json # Validates: sprite-spec-v1
│ ├── walk_spec.json
│ ├── run_spec.json
│ ├── jump_spec.json
│ ├── attack_spec.json
│ ├── hurt_spec.json
│ ├── death_spec.json
│ └── cast_spec.json
└── views/
├── front.png
└── thumbnail.png
SDK Schema Compliance¶
character.json (character-meta-v1)¶
{
"id": "Bolt",
"display_name": "Bolt",
"description": "A brave robot with glowing blue eyes and a jetpack",
"rarity": "common",
"tier": 1,
"tags": ["robot", "pixel_art"],
"views": {
"front": "views/front.png",
"thumbnail": "views/thumbnail.png"
},
"animations": {
"idle": { "tier": "mandatory", "frames": 6, "fps": 10 },
"walk": { "tier": "standard", "frames": 6, "fps": 10 },
"run": { "tier": "standard", "frames": 6, "fps": 14 },
"jump": { "tier": "mandatory", "frames": 4, "fps": 12 },
"attack": { "tier": "standard", "frames": 6, "fps": 14 },
"hurt": { "tier": "mandatory", "frames": 3, "fps": 10 },
"death": { "tier": "extended", "frames": 4, "fps": 10 },
"cast": { "tier": "extended", "frames": 5, "fps": 12 }
},
"sounds": {
"on_select": "sfx_character_select",
"on_hurt": "sfx_character_hurt",
"on_victory": "stinger_victory"
}
}
Sprite Spec (sprite-spec-v1)¶
{
"action": "idle",
"frames": 6,
"cell_size": 512,
"fps": 10,
"loop": true,
"layout": { "columns": 6, "rows": 1 }
}
IVX Export Module¶
The export layer transforms Content-Factory native output to SDK-compliant format:
# content-factory/utils/ivx_exporter.py
TIER_MAP = {
"idle": "mandatory", "walk": "standard", "run": "standard",
"jump": "mandatory", "hurt": "mandatory", "attack": "standard",
"death": "extended", "cast": "extended",
}
FPS_MAP = {
"idle": 10, "walk": 10, "run": 14, "jump": 12,
"hurt": 10, "attack": 14, "death": 10, "cast": 12,
}
LOOP_MAP = {
"idle": True, "walk": True, "run": True, "jump": False,
"attack": False, "hurt": False, "death": False, "cast": False,
}
def export_character_meta(name, description, sprites, views, style="pixel_art"):
char_id = re.sub(r'[^A-Za-z0-9]', '', name)
return {
"id": char_id,
"display_name": name,
"description": description,
"rarity": "common",
"tier": 1,
"tags": [style],
"views": {
"front": views.get("front", "views/front.png"),
"thumbnail": views.get("thumbnail", views.get("front", "views/front.png")),
},
"animations": {
action: {
"tier": TIER_MAP.get(action, "extended"),
"frames": data["frames"],
"fps": FPS_MAP.get(action, 10),
}
for action, data in sprites.items()
},
"sounds": {},
}
def export_sprite_spec(action, frames, cell_size=512):
return {
"action": action,
"frames": frames,
"cell_size": cell_size,
"fps": FPS_MAP.get(action, 10),
"loop": LOOP_MAP.get(action, False),
"layout": {"columns": frames, "rows": 1},
}
Validation¶
After generation, validate with SDK tools:
python tools/asset-pipeline/validate_character.py --character characters/Bolt/ivx/ --all
python tools/asset-pipeline/validate_specs.py --directory characters/Bolt/ivx/sprites/
Supported Styles¶
| Style | Prompt Modifier | Best For |
|---|---|---|
pixel_art | "32-bit pixel art, clean edges" | Platformers, retro, indie |
cartoon | "Cartoon style, bold outlines" | Casual, kids games |
anime | "Anime style, cel-shaded" | RPGs, visual novels |
realistic | "Semi-realistic, detailed" | Simulation, sports |
chibi | "Chibi proportions, cute" | Gacha, idle games |
flat_vector | "Flat design, minimal shading" | Puzzle, UI-heavy games |
Frame Counts Per Action¶
| Action | Frames | Cell Size | Layout | Tier |
|---|---|---|---|---|
| idle | 6 | 512×512 | 6×1 | mandatory |
| walk | 6 | 512×512 | 6×1 | standard |
| run | 6 | 512×512 | 6×1 | standard |
| jump | 4 | 512×512 | 4×1 | mandatory |
| attack | 6 | 512×512 | 6×1 | standard |
| hurt | 3 | 512×512 | 3×1 | mandatory |
| death | 4 | 512×512 | 4×1 | extended |
| cast | 5 | 512×512 | 5×1 | extended |
Engine Import¶
| Engine | Import Method |
|---|---|
| Unity | Sprite Editor → slice by cell size → AnimationClip per strip |
| Unreal | Paper2D Flipbook → import strip → set frame count |
| Godot | AnimatedSprite2D → load strip → set hframes |
| Defold | Atlas → tile source from strip → set frame dimensions |
| Roblox | Decal/SurfaceGui → individual frames extracted from strip |
| Cocos2d-x | SpriteFrame → create from strip rect |
Platform Notes¶
VR¶
- Generate at 1024×1024 cell size for VR readability
- Include front + side + back views for spatial presence
Console¶
- Texture budgets: Switch (512 max), PS5/Xbox (1024+ fine)
- Pre-generate topic skins for seasonal events
WebGL¶
- Use 256×256 cells to reduce download size
- Compress PNGs with pngquant before deployment
Mobile¶
- 512×512 is optimal for most mobile GPUs
- Generate @2x variants for high-DPI screens
Checklist¶
- Content-Factory API accessible (local Docker or cloud)
- Character description provided with name and style
- Pipeline triggered with
ivx_export: true -
character.jsonvalidates againstcharacter-meta-v1 - All
*_spec.jsonvalidate againstsprite-spec-v1 - Sprite strips have transparent backgrounds (alpha channel)
- Expression sheet has 6 emotions in 3×2 grid
- Emotional state PNGs generated (6 states)
- Promo assets generated (icon, thumbnail, key art, banner)
- Assets uploaded to S3 or local output directory
- Sprites imported into target engine
- AnimationClips/Flipbooks created from strips
- VR: cell size increased to 1024 if targeting Quest/VisionPro
- Console: texture budget verified
- WebGL: PNGs compressed