Builder puro (dict API format) del grupo gamedev: genera el workflow de UN emote/expresion facial del mismo personaje (alegre, triste, enfadado, sorprendido, neutral) para sistema de dialogo, retratos reactivos o emotes de chat. La clave es la consistencia del personaje entre expresiones: ref_face encadena IPAdapter-FaceID para que varie solo la expresion y el rostro sea el mismo; facedetailer regenera la cara conservando la expresion. Compone comfyui_build_ipadapter_workflow / comfyui_build_txt2img_workflow + comfyui_inject_lora + comfyui_build_facedetailer_workflow. Hermano de comfyui_build_portrait_avatar/sprite_sheet_workflow. 12 tests offline verdes (golden + edge + error) y 1 generacion real verificada en GPU (8GB lowvram): la expresion happy/smiling se lee claramente. Fila en docs/capabilities/gamedev-2d.md. Evidencia en reports/0151. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
11 KiB
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:
- 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 concomfyui_submit_workflow. - Post-proceso determinista (
gamedev, CPU): pixelizar, recortar a alpha. - 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). |
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.
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.
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_compositeinline.comfyui_build_gridNO sirve (aplana el alpha sobre fondo oscuro). Pendiente de R4 (planreports/0140F2). - 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_workflowproduce UN frame; la orquestación multi-pose es pipeline pendiente (planreports/0137T2). - Paletas lospec por red (
load_lospec_palette): no incluido.pixelizeusa 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_godotcopia 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_godotdeja el.importescrito 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.