Files
fn_registry/docs/capabilities/gamedev-2d.md
T
egutierrez d7387d9d2c feat(gamedev): comfyui_build_enemy_creature_workflow — enemigos/criaturas (cuerpo entero, alpha, variantes)
Nuevo builder del grupo gamedev/gamedev-2d para enemigos/criaturas de juego
(goblin, esqueleto, slime, dragon, boss, elemental): figura de cuerpo entero,
centrada, fondo limpio recortable a alpha, estilo consistente entre criaturas
del bestiario. Variantes por nivel/elemento (ice, fire, elite, corrupted) via
el argumento variant, que se antepone a la criatura base.

Funcion pura (dict API format) que compone funciones existentes del registry:
comfyui_build_txt2img_workflow + comfyui_inject_lora (estilo opcional) +
Image Rembg (fondo transparente). Hermano de comfyui_build_item_icon /
ui_hud / sprite_sheet_workflow.

- 8 tests offline verdes (golden/edge/error/determinismo)
- .md autosuficiente (Ejemplo + Cuando usarla + Gotchas)
- fila en docs/capabilities/gamedev-2d.md
- probado e2e en GPU (8GB lowvram, SD1.5): goblin warrior ice cuerpo entero,
  512x512 RGBA con alpha, prompt_id e770d050 (report 0154)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 23:29:54 +02:00

136 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Capability group: `gamedev` / `gamedev-2d` — assets 2D para Godot (generación + post-proceso + puente)
Cluster de funciones para producir y mover assets 2D de juego entre **ComfyUI**
(generación) y **Godot 4** (consumo). Tres capas:
1. **Builders de workflow 2D** (`gamedev-2d`, GPU): construyen el dict (API format)
de los workflows ComfyUI para pixel-art, tiles seamless, isométrico, sprites de
personaje y VFX en bucle. Son **puros** (no tocan GPU al construir); el coste GPU
está al enviar con `comfyui_submit_workflow`.
2. **Post-proceso determinista** (`gamedev`, CPU): pixelizar, recortar a alpha.
3. **Puente de assets** (`gamedev`, CPU): coloca el resultado en un proyecto Godot
con sus import settings.
Tags: `gamedev` (post-proceso + puente) y `gamedev-2d` (builders de workflow).
Filtro: `mcp__registry__fn_search query="" tag="gamedev-2d"`.
Documento hermano del grupo `comfyui` (generación genérica de imágenes/video/3D).
Diseño del puente: `docs/comfyui-godot-integration.md`. Planes origen: `reports/0135`
(pixelart), `reports/0139` (entornos/tiles/iso), `reports/0137` (personajes/sprites),
`reports/0140` (VFX), `reports/0143` (ronda 2b: builders), `reports/0147` (item icons),
`reports/0149` (parallax background).
## Builders de workflow 2D (`gamedev-2d`, puros — generación)
Construyen el dict API format listo para `comfyui_submit_workflow`. Cada uno compone
funciones existentes del registry (`comfyui_build_txt2img_workflow`, `comfyui_inject_*`,
`comfyui_build_ipadapter_workflow`) — no reinventan el grafo. class_types verificados
contra `/object_info` del server (8GB lowvram). Probados e2e en GPU: pixelart, seamless,
VFX (ver `reports/0143`).
| ID | Firma corta | Qué hace |
|---|---|---|
| `comfyui_build_pixelart_workflow_py_ml` | `(positive, negative=…, *, ckpt_name="juggernaut_xl_v11…", pixel_lora="pixel-art-xl…", use_lcm=True, …) -> dict` | Fase 1 pixel-art: SDXL + LoRA pixel-art-xl (+ LCM 8 steps). El pixel-perfect es post (`comfyui_pixelize_image`). |
| `comfyui_build_seamless_tile_workflow_py_ml` | `(positive, negative="", *, tiling="enable", copy_model="Make a copy", circular_vae=True, material_lora=None, …) -> dict` | Textura tileable: `SeamlessTile` (Conv2d circular) + `CircularVAEDecode`. Coste VRAM ≈0. |
| `comfyui_build_isometric_workflow_py_ml` | `(positive, negative=…, *, iso_lora="isometric_game_assets_sd15…", grid_image=None, …) -> dict` | Asset iso 2:1: LoRA iso + ControlNet grid opcional. |
| `comfyui_build_sprite_sheet_workflow_py_ml` | `(subject, *, ref_image=None, pose_skeleton=None, char_lora=None, transparent=True, …) -> dict` | UN sprite de personaje: IPAdapter-FaceID + LoRA + ControlNet OpenPose (Advanced, end<1) + Rembg. Varias poses → sheet. SD1.5. |
| `comfyui_build_vfx_spritesheet_workflow_py_ml` | `(prompt, *, motion_model="mm_sd_v15_v2.ckpt", num_frames=16, closed_loop=True, lora=None, …) -> dict` | N frames AnimateDiff loop sobre negro (insumo de luma→alpha). 8GB: 16f@512² revienta, usar ≤8f@512² o bajar resolución. |
| `comfyui_build_item_icon_workflow_py_ml` | `(item, *, style="game icon, clean, centered", checkpoint="dreamshaper_8…", size=512, transparent=True, lora=None, …) -> dict` | UN icono de item de inventario (espada/poción/anillo/libro/escudo): txt2img cuadrado + prompt scaffold de icono + LoRA estilo opcional + Rembg (alpha). Set coherente = mismo style/checkpoint/lora por item. SD1.5. |
| `comfyui_build_portrait_avatar_workflow_py_ml` | `(character, *, style="character portrait", ref_face=None, checkpoint="dreamshaper_8…", size=512, facedetailer=True, lora=None, …) -> dict` | UN retrato/avatar de personaje (busto centrado, cara al espectador, fondo simple): txt2img + prompt scaffold de retrato + FaceDetailer (cara nítida) + LoRA estilo opcional; `ref_face` → IPAdapter-FaceID para rostro consistente entre retratos. Diálogo/perfil/selección. SD1.5. |
| `comfyui_build_emote_workflow_py_ml` | `(character, expression, *, ref_face=None, style="character portrait", checkpoint="dreamshaper_8…", size=512, facedetailer=True, lora=None, …) -> dict` | UN emote/expresión facial del MISMO personaje (alegre/triste/enfadado/sorprendido/neutral…) para diálogo, retratos reactivos o emotes de chat: txt2img + prompt scaffold de emote (`portrait of {character}, {expression} expression, emote, clean background`) + FaceDetailer (conserva la expresión); `ref_face` → IPAdapter-FaceID para que varíe SOLO la expresión y el rostro sea el mismo. UNA expresión por llamada; set = mismas claves variando `expression``comfyui_build_grid`. Probado e2e en GPU (`reports/0151`). SD1.5. |
| `comfyui_build_parallax_background_workflow_py_ml` | `(scene, *, style="game background, side-scroller…", layers=3, checkpoint="dreamshaper_8…", depth_node="DepthAnythingV2Preprocessor", width=1024, height=512, …) -> dict` | Fondo en capas para parallax 2.5D: genera el fondo apaisado (txt2img) + su depth map (`DepthAnythingV2Preprocessor` sobre el VAEDecode), dos SaveImage. El split en N bandas por profundidad es post (GAP: `split_parallax_layers`, aún no creada). Probado e2e en GPU (`reports/0149`). SD1.5. |
| `comfyui_build_normal_map_workflow_py_ml` | `(image, *, method="normal", strength=1.0, resolution=512, bg_threshold=0.1, filename_prefix="normal_map") -> dict` | Normal/depth map de un sprite existente para iluminación dinámica 2.5D (Godot CanvasItem `normal_map`, Unity sprite normal). `LoadImage → preprocesador controlnet_aux → SaveImage`. `method`: `normal` (default, `BAE-NormalMapPreprocessor`, normal canónico **azul/violeta** usable directo en motor), `normal_midas` (MiDaS, único con `strength``a`, paleta no canónica), `normal_dsine` (DSINE), `depth` (`DepthAnythingV2`, height en gris). `image` debe estar en `input/` de ComfyUI. Coste VRAM ≈0. Probado e2e en GPU (`reports/0150`). |
| `comfyui_build_ui_hud_workflow_py_ml` | `(element, *, ui_style="fantasy game UI", checkpoint="dreamshaper_8…", size=512, transparent=True, lora=None, …) -> dict` | UN elemento de interfaz/HUD de juego (botón, marco/panel, barra de vida/maná/XP, icono de UI, cursor, viñeta de menú): txt2img cuadrado + prompt scaffold de UI (`{element}, {ui_style}, game UI element, centered, clean, plain background…`) + LoRA estilo opcional + Rembg (alpha). HUD coherente = mismo `ui_style`/`checkpoint`/`lora` por pieza, varía solo `element`. El texto/label lo pone el motor (negativo empuja a `no text`). Probado e2e en GPU (`reports/0152`). SD1.5. |
| `comfyui_build_card_art_workflow_py_ml` | `(subject, *, card_style="fantasy trading card art", checkpoint="juggernaut_xl_v11…", width=512, height=768, hires=True, seed=0, lora=None, …) -> dict` | LA ilustración central de UNA carta coleccionable (TCG): criatura/personaje/hechizo en formato **vertical** de carta (`width<height`, ~512×768), composición centrada + iluminación dramática (`{subject}, {card_style}, dramatic lighting, detailed illustration, centered composition, full art…`). `hires=True` → 2ª pasada de detalle (`comfyui_build_hires_fix_workflow`); si no, txt2img + LoRA estilo opcional. Genera SOLO la ilustración — el marco/título/stats los pone el motor/post (negativo rechaza `card frame/border/text/stats/UI`). Set coherente = mismo `card_style`/`checkpoint`/`lora`, varía solo `subject`. Probado e2e en GPU con SD1.5 (`reports/0153`); ⚠️ el path `hires=True` falla hoy por bug del builder `comfyui_build_hires_fix_workflow` (nodo `UltimateSDUpscale` pide `batch_size`) — usar `hires=False` hasta el fix. SD1.5/SDXL. |
| `comfyui_build_enemy_creature_workflow_py_ml` | `(creature, *, variant=None, style="game creature, full body", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict` | UN enemigo/criatura de juego (goblin, esqueleto, slime, dragón, boss, elemental): figura de **cuerpo entero** centrada, fondo limpio recortable a alpha (`{variant} {creature}, {style}, full body, centered, plain background, game asset…`) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). `variant` (ice/fire/elite/corrupted…) se antepone a la criatura para generar la familia del MISMO enemigo (misma `creature`/`seed`/`style`, varía solo `variant`); bestiario coherente = mismo `style`/`checkpoint`/`lora`, varía solo `creature`. El negativo empuja a UNA criatura entera sin recorte. Probado e2e en GPU con SD1.5 (`reports/0154`). SD1.5. |
## Funciones de post-proceso y puente (`gamedev`, CPU)
| ID | Firma corta | Qué hace |
|---|---|---|
| `comfyui_pixelize_image_py_ml` | `(src, dst, *, downscale=8, colors=16, palette=None, dither=False, upscale_back=True) -> dict` | Pixel-perfect: downscale nearest + cuantización a N colores o paleta fija (game-boy/pico-8/nes). Fase 2 pixelart. Impura (I/O). |
| `comfyui_matting_luma_to_alpha_py_ml` | `(image_path, *, out_path=None, gamma=1.0, black_point=0.0, premultiply=False, luma_weights=(.299,.587,.114)) -> dict` | Frame VFX sobre negro -> RGBA usando luminancia como alpha (translúcidos con additive blend). Impura (I/O). |
| `comfyui_export_asset_to_godot_py_pipelines` | `(asset_path, kind, godot_project, *, name=None, reimport=True, godot_bin=None) -> dict` | Copia el asset a `res://assets/<dir>/` por `kind` + escribe `.import` + filtro Nearest si pixelart + reimport headless. Pipeline impuro. |
| `godot_map_asset_dir_py_core` | `(kind) -> str` | Mapea `kind` -> subcarpeta de `res://assets/`. Pura. |
| `godot_clean_asset_name_py_core` | `(filename, *, override=None) -> str` | Normaliza el nombre `<prefijo>_NNNNN_.<ext>` a snake_case seguro para `res://`. Pura. |
## Ejemplo end-to-end con builder (Fase 1 GPU → Fase 2 CPU → Godot)
Flujo completo pixel-art: construir workflow → generar en ComfyUI → pixel-perfect → Godot.
```python
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_build_pixelart_workflow import comfyui_build_pixelart_workflow
from ml.comfyui_submit_workflow import comfyui_submit_workflow
from ml.comfyui_wait_result import comfyui_wait_result
from ml.comfyui_fetch_output_image import comfyui_fetch_output_image
from ml.comfyui_pixelize_image import comfyui_pixelize_image
# 1. Construir (puro) + 2. generar (GPU)
wf = comfyui_build_pixelart_workflow("isometric tiny house, pixel, 32x32 style", use_lcm=True, seed=42)
pid = comfyui_submit_workflow(wf)["prompt_id"]
outs = comfyui_wait_result(pid, timeout=300)
fn = next(img["filename"] for o in outs.values() for img in o.get("images", []))
raw = comfyui_fetch_output_image(fn, dest_dir="/tmp")["out_path"]
# 3. pixel-perfect (CPU) -> 4. export Godot (ver ejemplo de abajo)
px = comfyui_pixelize_image(raw, "/tmp/house_pixel.png", downscale=8, colors=16)
```
VFX: `comfyui_build_vfx_spritesheet_workflow(prompt, num_frames=8)` → submit → fetch N frames
`comfyui_matting_luma_to_alpha` por frame → montar sheet RGBA con `Image.alpha_composite`
(NO `comfyui_build_grid`, que aplana el alpha).
## Ejemplo canónico de post-proceso
Flujo: crudo generado en ComfyUI -> pixelizar -> exportar a Godot con Nearest.
```python
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_pixelize_image import comfyui_pixelize_image
from ml.comfyui_matting_luma_to_alpha import comfyui_matting_luma_to_alpha
from pipelines.comfyui_export_asset_to_godot import comfyui_export_asset_to_godot
OUT = os.path.expanduser("~/ComfyUI/output")
PROJ = os.path.expanduser("~/gamedev/projects/crossy_road")
# 1. Pixelizar un sprite crudo (SDXL+pixel-art-xl) a 16 colores
px = comfyui_pixelize_image(f"{OUT}/hero_00001_.png", "/tmp/hero_pixel.png",
downscale=8, colors=16)
# 2. Exportarlo a Godot como pixelart (carpeta sprites/, filtro Nearest, reimport)
exp = comfyui_export_asset_to_godot("/tmp/hero_pixel.png", "pixelart", PROJ)
print(exp["dest_res_path"], exp["pixelart_filter_set"], exp["reimported"])
# Rama VFX: frame de humo sobre negro -> RGBA -> carpeta vfx/
rgba = comfyui_matting_luma_to_alpha(f"{OUT}/vfx_loop_00007_.png", gamma=1.2, black_point=0.04)
comfyui_export_asset_to_godot(rgba["out_path"], "vfx", PROJ)
```
## Fronteras (qué NO cubre)
- **Montaje de spritesheet dedicado** (grid RGBA + JSON sidecar para Godot/Unity):
no hay función propia todavía — el ejemplo VFX monta con `Image.alpha_composite`
inline. `comfyui_build_grid` NO sirve (aplana el alpha sobre fondo oscuro). Pendiente
de R4 (plan `reports/0140` F2).
- **Pipelines one-shot** (build → submit → wait → fetch → post en una call) para
pixelart/sprite/VFX: pendientes. Hoy se encadena a mano (ver ejemplos). Candidatos a
promoción a pipeline (issue 0087) cuando el patrón se repita.
- **Sprite turnaround multi-vista** (orquestar N poses con identidad fija + juez):
el builder `comfyui_build_sprite_sheet_workflow` produce UN frame; la orquestación
multi-pose es pipeline pendiente (plan `reports/0137` T2).
- **Paletas lospec por red** (`load_lospec_palette`): no incluido. `pixelize` usa
paletas fijas embebidas (game-boy/pico-8/nes) o lista de hex, sin HTTP.
- **TileSet / SpriteFrames `.tres`**: Godot no los deriva solos; `export_asset_to_godot`
copia la textura y avisa, pero no genera el recurso (paso manual o futura función).
## Prerequisitos / notas
- **Godot CLI** para el reimport headless: autodetectado en PATH y en
`~/godot/Godot_v4.7-stable_linux.x86_64`. Si falta, `export_asset_to_godot` deja el
`.import` escrito y lo anota (no falla).
- **Filtro Nearest (Godot 4)**: se setea global en `project.godot`
(`default_texture_filter=0`), no por `.import`. La función lo asegura para pixelart.
- CPU-only: Pillow + numpy del venv del registry. Cero VRAM, cero red.