Tercer eje del catálogo gamedev-2d: partir del DIBUJO del dev. Recibe un boceto/lineart + un prompt de qué es y construye un workflow txt2img guiado por ControlNet (lineart/scribble/canny) que pinta el sprite conservando la forma dibujada. Distinto de los builders txt2img (inventan la forma desde texto) y de asset_variant img2img (reescribe una imagen ya pintada conservando forma+color): aquí el dev marca la silueta y la IA pone material/color/acabado, conservando solo la forma. Función pura (API format). Compone comfyui_build_txt2img_workflow + comfyui_inject_controlnet + comfyui_inject_lora; el único código propio es el helper que interpone el preprocesador (LineArt/Scribble/Canny) entre el boceto y el ControlNet, análogo a _inject_image_scale del hermano asset_variant. control_type selecciona preprocesador y modelo CN emparejado; controlnet_name y preprocess dan override para degradar al modelo disponible. Gotcha documentado: el server 8GB solo tiene modelos CN SD1.5 canny/depth/openpose — para lineart/scribble usar override a canny o control_type=canny (pendiente humano descargar los modelos lineart/scribble dedicados). Verificación: tests offline verdes (cableado txt2img guiado, 3 control_types, clamps, errores). E2E real GPU SD1.5: boceto del goblin → CannyEdgePreprocessor → ControlNet canny → sprite que respeta pose/orejas/hombrera/lanza/espada del dibujo (prompt_id ea6fc372, edge corr 0.545, luminance corr -0.19 confirmando repintado). Report en reports/0182. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
46 KiB
Capability group: 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 (CPU): pixelizar, recortar a alpha.
- Puente de assets (CPU): coloca el resultado en un proyecto Godot con sus import settings.
Tag único del grupo: gamedev-2d (los 31 builders de workflow + las 5 funciones de
apoyo de post-proceso y puente). El tag plano gamedev quedó deprecado y unificado a
gamedev-2d. El runtime de juego C++ (el motor que ejecuta el juego: game loop,
cámara, input, render por lotes, audio) vive en el grupo hermano gamedev-engine.
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_dialogue_box_workflow_py_ml |
(box_style="fantasy RPG dialogue box", *, shape="rounded panel", checkpoint="dreamshaper_8…", width=768, height=256, transparent=True, seed=0, lora=None, …) -> dict |
EL contenedor de diálogo / bocadillo / panel de texto de juego (RPG, visual novel, aventura): marco apaisado (width>height, 768×256) con borde decorativo y un interior plano/vacío reservado para que el motor renderice el texto de la conversación encima → {box_style}, {shape}, game UI dialogue box frame, ornate border, empty flat interior for text, plain background + LoRA estilo opcional + Rembg (alpha). DISTINTO de ui_hud (elementos sueltos: botón/barra/icono): esto es el panel-contenedor completo. shape (rounded panel/scroll parchment/stone tablet/speech bubble…) + set coherente = mismo box_style/shape/checkpoint/lora. El interior se mantiene liso (negativo rechaza busy/decorated interior); el texto lo pone el motor (negativo empuja a no text). Probado e2e en GPU con SD1.5 — medieval fantasy dialogue box, wood and gold 768×256 RGBA, panel madera+oro con interior plano y alpha (reports/0171). SD1.5. |
comfyui_build_status_effect_icon_workflow_py_ml |
(effect, *, ui_style="game status icon, bold symbol, flat", checkpoint="dreamshaper_8…", size=256, transparent=True, seed=0, lora=None, …) -> dict |
UN icono de estado / buff-debuff (veneno, quemadura, congelación, escudo, regeneración, aturdimiento, velocidad, sangrado, maldición): símbolo compacto que se superpone al HUD para indicar un efecto activo, optimizado para legibilidad a tamaño reducido (16-32 px) → {effect} status effect icon, {ui_style}, simple bold symbol, centered, readable at small size, plain background… + LoRA estilo opcional + Rembg (alpha). size por defecto menor (256, no 512) porque se muestra pequeño; el negativo rechaza intricate details/complex/cluttered para no perder legibilidad. DISTINTO de item_icon (objeto de inventario) y ui_hud (chrome grande de interfaz): aquí es un símbolo de estado. Barra coherente = mismo ui_style/checkpoint/lora, varía solo effect (color habla del tipo). El texto/contador lo pone el motor (negativo empuja a no text). Probado e2e en GPU con SD1.5 — poison 256×256 RGBA, símbolo verde flat centrado (reports/0162). SD1.5. |
comfyui_build_skill_tree_node_workflow_py_ml |
(skill, *, frame="hexagonal", state="unlocked", ui_style="fantasy skill tree node", checkpoint="dreamshaper_8…", size=256, transparent=True, seed=0, lora=None, …) -> dict |
UN nodo de árbol de habilidades / talentos (RPG, ARPG, MOBA, roguelike): el icono de una skill DENTRO de un marco (frame: hexagonal/circular/diamond/shield) que la UI de progresión pinta en la rejilla, con variante de estado visual (state: unlocked=brillante/saturado, locked=gris/desaturado) → {skill} skill icon inside a {frame} {ui_style} frame, {state} (…hint…), centered, plain background, game UI, skill tree talent node… + LoRA estilo opcional + Rembg (alpha). El marco y el estado son la firma del asset. DISTINTO de item_icon (objeto suelto sin marco), status_effect_icon (símbolo superpuesto sin marco) y ui_hud (chrome grande): aquí es el nodo enmarcado completo de la pantalla de talentos. Par de un mismo talento = mismo skill/frame/ui_style/seed, varía solo state (las dos caras de la rejilla). Árbol coherente = mismo frame/ui_style/checkpoint/lora, varía skill. El texto/coste lo pone el motor (negativo empuja a no text). Probado e2e en GPU con SD1.5 — fireball hexagonal unlocked 256×256 RGBA, nodo enmarcado brillante centrado (reports/0173). SD1.5. |
comfyui_build_achievement_badge_workflow_py_ml |
(badge, *, tier="gold", style="game achievement badge, ornate", checkpoint="dreamshaper_8…", size=256, transparent=True, seed=0, lora=None, …) -> dict |
UNA insignia / medalla / logro (achievement, recompensa, rango): un trofeo, una medalla con cinta, un escudo de logro o un badge de rango que el panel de logros pinta al desbloquear un hito, con tier metálico (bronze/silver/gold/platinum/diamond) que distingue el grado → {badge} achievement badge, {tier} tier (…hint metálico…), {style}, medal with ribbon, centered, plain background, game UI reward, trophy emblem… + LoRA estilo opcional + Rembg (alpha). El tier metálico y la forma de medalla/trofeo con cinta son la firma del asset. DISTINTO de item_icon (objeto de inventario suelto, sin tier ni cinta), status_effect_icon (símbolo de estado superpuesto sin marco) y skill_tree_node (nodo enmarcado de la rejilla de talentos con estado unlocked/locked): aquí es la insignia de logro/recompensa del panel de achievements. Familia de un mismo logro = mismo badge/style/seed, varía solo tier (los grados); set coherente = mismo style/checkpoint/lora, varía badge. El nombre/descripción/fecha lo pone el motor (negativo empuja a no text). Probado e2e en GPU con SD1.5 — dragon slayer tier gold seed 77 256×256 RGBA, medalla circular dorada con emblema centrado y fondo recortado a alpha (esquina α=0, centro α=254; prompt_id 8b8b7ede, reports/0175). 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. |
comfyui_build_prop_object_workflow_py_ml |
(prop, *, style="game prop, isometric or side view", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN prop/objeto de escenario (barril, cofre, antorcha, planta, mueble, roca, fuente, estatua): objeto inanimado aislado a escala de escena y perspectiva de juego (iso/lateral), centrado, fondo limpio recortable a alpha ({prop}, {style}, game asset, single object, centered, plain background, scene prop, world object…) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). Objeto de MUNDO, no icono plano de inventario (≠ item_icon, que es para una casilla de UI); este puebla el nivel. Atrezzo coherente = mismo style/checkpoint/lora, varía solo prop. El negativo excluye personas/criaturas (objeto inanimado). Probado e2e en GPU con SD1.5 (reports/0155). SD1.5. |
comfyui_build_vehicle_mount_workflow_py_ml |
(vehicle, *, view="side", style="game vehicle", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN vehículo/montura que el personaje USA o CONDUCE (caballo, dragón-montura, nave espacial, coche, barco, carro, grifo, mecha): el vehículo COMPLETO en vista lateral o isométrica, centrado, fondo limpio recortable a alpha, SIN jinete/conductor ({vehicle}, {view} view, {style}, full vehicle, centered, plain background, game asset, no rider, empty…) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). Se genera VACÍO (el negativo rechaza person/rider/driver/passenger) para que el motor componga al personaje encima. DISTINTO de enemy_creature (sujeto a COMBATIR) y prop_object (atrezzo inanimado que decora): aquí el objeto se MONTA/USA; una montura viva que se cabalga (caballo, dragón) entra aquí, no en enemy_creature. view (side/iso) fija la geometría del parque móvil; set coherente = mismo view/style/checkpoint/lora, varía solo vehicle. Probado e2e en GPU con SD1.5 — armored war horse with saddle side 512×512 RGBA, vehículo centrado recortado a alpha (centroide 0.55/0.54, 4 esquinas transparentes, reports/0169). SD1.5. |
comfyui_build_topdown_sprite_workflow_py_ml |
(subject, *, direction="south", style="top-down game sprite, RPG", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN sprite en vista CENITAL (top-down) estilo RPG clásico/roguelike (Zelda, juegos cenitales): personaje/objeto visto desde arriba, centrado, fondo limpio recortable a alpha ({subject}, top-down view, overhead view, {direction} facing, {style}, centered, plain background, game asset…) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). direction (south/north/east/west) para el sprite de movimiento: las 4 vistas del MISMO personaje = misma subject/style/seed, varía solo direction → montar con comfyui_build_grid. DISTINTO de sprite_sheet (vista lateral/frontal de plataformas): el negativo por defecto rechaza side/front/3-4/isometric/perspective para forzar la cenital. Con SD1.5 sin LoRA sale picado alto; cenital estricto pide LoRA top-down + cfg alto. Probado e2e en GPU con SD1.5 (reports/0156). SD1.5. |
comfyui_build_splash_art_workflow_py_ml |
(scene, *, mood="epic, cinematic", checkpoint="juggernaut_xl_v11…", width=1024, height=576, hires=True, seed=0, lora=None, …) -> dict |
LA ilustración grande de UN splash / pantalla de carga / key art en formato pantalla apaisado 16:9 (width>height, ~1024×576), composición cinematográfica ({scene}, {mood}, key art, game splash screen, dramatic lighting, cinematic composition, wide shot, epic scale, atmospheric…). hires=True → 2ª pasada de detalle (comfyui_build_hires_fix_workflow) para verse a pantalla completa; si no, txt2img + LoRA estilo opcional. Genera SOLO la ilustración — el título/logo/barra de carga los pone el motor/post (negativo rechaza text/title/logo/UI/frame/watermark), dejando aire para superponer el título. Set coherente = mismo mood/checkpoint/lora, varía solo scene. Probado e2e en GPU con SD1.5 + hires (1024×576 → 1536×864, 54s, reports/0159). SD1.5/SDXL. |
comfyui_build_world_map_workflow_py_ml |
(region, *, map_style="fantasy cartography, aged parchment", checkpoint="juggernaut_xl_v11…", width=768, height=768, hires=False, seed=0, lora=None, …) -> dict |
LA ilustración de la pantalla de mapa del juego: una lámina cartográfica en vista cenital de un continente/región/reino/mazmorra con aspecto de atlas fantasy (map of {region}, {map_style}, top-down cartographic view, illustrated game world map, labeled regions, decorative border, compass rose, fantasy atlas, no people…). Cuadrado por defecto (768×768; sube width para mundo apaisado, height para mazmorra en columna), hires=False por defecto (ponlo True para detalle fino de costas/relieve). Genera SOLO la ilustración — las marcas interactivas, los iconos pinchables, las rutas y el "estás aquí" los pone el motor SOBRE la lámina; la difusión dibuja labels/ornamentos DECORATIVOS pero NO garantiza ortografía ni posiciones usables como datos (el negativo rechaza photo/3d render/perspective/character/person para mantener la vista cenital plana). Atlas coherente = mismo map_style/checkpoint/lora, varía solo region. Probado e2e en GPU con SD1.5 — reino fantasy 768×768, lámina de pergamino con costas/montañas/regiones + borde ornamental + rosa de los vientos (prompt_id bf4861fc, reports/0167). SD1.5/SDXL. |
comfyui_build_decal_overlay_workflow_py_ml |
(decal, *, on_black=True, style="grunge decal, high detail", checkpoint="dreamshaper_8…", size=512, seed=0, lora=None, …) -> dict |
UN decal/overlay con alpha para superponer sobre superficies/paredes/sprites con blend mode del motor (sangre, grietas, suciedad, óxido, quemaduras, salpicaduras, arañazos, musgo): textura aislada sobre fondo PLANO ({decal}, {style}, single isolated decal, centered, on a solid pure black background, flat backdrop, sticker, no scenery, texture overlay, game asset…) → txt2img cuadrado + LoRA estilo opcional. on_black=True (defecto) pensado para extraer alpha con comfyui_matting_luma_to_alpha (luma=alpha, conserva el falloff de translúcidos — la técnica gamedev correcta, ≠ recorte binario). NO inyecta Rembg (el matting es luma→alpha de disco, no un nodo): el SaveImage sale directo del VAEDecode. Set coherente = mismo style/checkpoint/lora, varía solo decal/seed. ⚠️ "grunge" en style arrastra fondo gris en SD1.5 → para fondo negro plano usar un style sin connotación de fondo + reroll de seed; luma Rec601 penaliza el rojo → para sangre roja pasar luma_weights con más peso al rojo. Probado e2e en GPU con SD1.5 (reports/0160). SD1.5. |
comfyui_build_projectile_workflow_py_ml |
(projectile, *, direction="right", glow=False, style="game projectile, side view", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN proyectil orientado (flecha, bala, bola de fuego, rayo, misil, hechizo): sprite pequeño con orientación (apunta a la derecha por defecto, ángulo 0 — el motor rota el sprite), aislado, listo para instanciar. glow elige el camino a alpha: glow=False (defecto) = proyectil SÓLIDO con silueta → plain background + Rembg (alpha por recorte, como item_icon/topdown_sprite); glow=True = brillante/mágico → glowing, on black background sin Rembg (recortaría el halo), insumo de comfyui_matting_luma_to_alpha que el caller aplica luego (como vfx_spritesheet/decal_overlay). glow=True ignora transparent/rembg_model; el negativo por defecto NO rechaza "black background". direction se inserta como pointing {direction} (""/None = sin orientación). Set coherente = mismo style/checkpoint/lora, varía solo projectile/seed. Probado e2e en GPU con SD1.5 — fireball glow sobre negro + luma→alpha RGBA (reports/0161). SD1.5. |
comfyui_build_structure_workflow_py_ml |
(structure, *, view="isometric", style="game building", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN edificio/estructura de escenario (casa, torre, castillo, tienda, posada, ruina, muralla, puente, templo, faro): UN building COMPLETO y centrado a perspectiva de juego ({view} view, iso por defecto), fondo limpio recortable a alpha ({structure}, {view} view, {style}, full building, complete structure, single building, centered, plain background, game asset, architecture…) → txt2img cuadrado + LoRA estilo/iso opcional + Rembg (alpha). EDIFICACIÓN grande que ocupa varios tiles y define el escenario, no un objeto pequeño suelto (≠ prop_object, que es atrezzo que se deja sobre un tile); el negativo rechaza small object / single item / prop / furniture. view fija la perspectiva del mapa (iso/side/front/top-down/¾); LoRA iso fija mejor el ángulo 2:1. Set coherente = mismo view/style/checkpoint/lora, varía solo structure. Probado e2e en GPU con SD1.5 — medieval blacksmith shop iso 512×512 RGBA, edificio centrado recortado a alpha (centroide 0.54/0.53, reports/0164). SD1.5. |
comfyui_build_foliage_set_workflow_py_ml |
(plant, *, view="side", style="game foliage, stylized", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN elemento de vegetación/foliage de escenario (árbol, arbusto, hierba alta, flores, helecho, hongo, cactus, tronco caído, juncos, hiedra): UN elemento de naturaleza ORGÁNICA AISLADO y centrado a perspectiva de juego ({view} view, side por defecto), fondo limpio recortable a alpha ({plant}, {view} view, {style}, single plant element, centered, plain background, game nature asset, natural vegetation, organic, isolated plant…) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). Vegetación que viste el terreno, distinta del objeto MANUFACTURADO suelto (≠ prop_object: barril/cofre/mueble) y del EDIFICIO (≠ structure: casa/torre); el negativo rechaza building / manmade object / barrel / furniture / person y multiple plants / dense forest / jungle / landscape (UN elemento, no un bosque) + pot / planter / vase (planta en maceta = prop_object). Recorte por Rembg (planta opaca de silueta definida), no luma→alpha. Set coherente = mismo view/style/checkpoint/lora, varía solo plant. ⚠️ dos gotchas reales SD1.5+Rembg: (1) plantas grandes (árbol) tienden a PAISAJE (cielo+campo) en lugar de fondo plano → re-roll de seeds buscando fondo uniforme (comfyui_batch_generate); (2) follaje verde claro sobre fondo claro → Rembg se come las hojas y deja solo tronco/ramas → preferir elementos de silueta compacta y color saturado (hongo, arbusto denso) o transparent=False + matting manual. Probado e2e en GPU con SD1.5 — golden a glowing mushroom seed 7 512×512 RGBA, hongo centrado recortado a alpha limpio (centroide 0.51/0.58, opaco 19%, prompt_id 8fb65a51); evidencia del gotcha del roble en reports/0170. SD1.5. |
comfyui_build_trap_hazard_workflow_py_ml |
(hazard, *, view="side", style="game hazard trap", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UNA trampa/peligro JUGABLE de nivel (pinchos del suelo, sierra giratoria, foso de lava, placa de presión, columna de llamas, trampa de flechas, charco ácido, descarga eléctrica, prensa, estaca cayendo): UN objeto de peligro AISLADO y centrado a perspectiva de juego ({view} view, side por defecto), fondo limpio recortable a alpha ({hazard}, {view} view, {style}, single hazard object, trap, dangerous, centered, plain background, game asset, high detail) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). Peligro al que el motor asigna hitbox de daño + estado activo/inactivo, distinto del objeto INERTE de decoración (≠ prop_object: barril/cofre que solo ambienta) y del enemigo VIVO (≠ enemy_creature); el negativo rechaza character / person / creature / multiple objects para que salga el mecanismo, no un enemigo ni una escena. Recorte por Rembg (trampa sólida de silueta definida: pinchos/sierra/placa); ⚠️ para hazards puramente etéreos (columna de llamas, arco eléctrico, gas) usar transparent=False + comfyui_matting_luma_to_alpha (conserva el falloff translúcido para blend aditivo), no Rembg. view fija la perspectiva del nivel (side/top-down/iso); set coherente = mismo view/style/checkpoint/lora, varía solo hazard. Probado e2e en GPU con SD1.5 — spiked floor trap side seed 7 512×512 RGBA, mecanismo de peligro centrado recortado a alpha (alpha extrema 0–255, fondo transparente real, prompt_id ab1b1560, reports/0174). SD1.5. |
comfyui_build_particle_texture_workflow_py_ml |
(particle, *, soft=True, style="particle texture, soft glow", checkpoint="dreamshaper_8…", size=256, seed=0, lora=None, …) -> dict |
UNA textura de partícula individual reutilizable (chispa, humo, polvo, destello/flare, gota, copo, hoja, círculo de energía) — el "ladrillo" que el sistema de partículas del motor (Godot GPUParticles2D, Unity VFX Graph) instancia a miles y anima (spawn/fade/color over lifetime). Aislada y centrada sobre fondo NEGRO (`{particle} particle, {style}, isolated on pure black background, <soft |
comfyui_build_weather_overlay_workflow_py_ml |
(weather, *, on_black=True, style="weather overlay, atmospheric", checkpoint="dreamshaper_8…", width=1024, height=576, seed=0, lora=None, …) -> dict |
UNA capa de clima/atmósfera a PANTALLA COMPLETA que cubre toda la vista del jugador y se superpone sobre la escena con blend del motor (lluvia, niebla, nieve, rayos de sol/god rays, polvo, viñeta de tormenta): cobertura uniforme de borde a borde, generada APAISADA a resolución de pantalla (16:9, 1024×576 por defecto — width>height, NO cuadrado) ({weather} overlay, {style}, full screen atmospheric layer, <particles/streaks on pure black background | translucent layer>, seamless full screen coverage, edge to edge, game VFX…) → txt2img apaisado + LoRA estilo opcional. on_black elige el modo de blend: on_black=True (defecto) = clima BRILLANTE sobre NEGRO puro (estrías de lluvia, copos, haces de luz, motas), sin Rembg, insumo de comfyui_matting_luma_to_alpha (luma=alpha, blend aditivo/screen — el negro desaparece, el clima brilla sobre la escena); on_black=False = película TRANSLÚCIDA semi-transparente (niebla densa, tinte de tormenta) para blend multiply/overlay o alpha global. El negativo rechaza solid object/single subject/character/building/landscape scene/horizon line/frame (cobertura total, NO un sujeto centrado) + (si on_black) blue sky/gray/white background para forzar negro plano. DISTINTO de decal_overlay (ése es una mancha LOCALIZADA que se pega en un punto de una superficie) y de vfx_spritesheet (ése es la SECUENCIA animada de UN efecto puntual): la capa de clima es UNA película estática de cobertura full-screen que el motor anima por scroll/loop/shader. Set coherente = mismo style/checkpoint/lora, varía weather/seed. ⚠️ algunos climas (lluvia/niebla) pintan cielo azul de fondo en SD1.5 aunque pidas negro → subir cfg + re-roll de seed; climas brillantes-sobre-negro (god rays, snow, sparks) salen más limpios que los difusos (fog). luma Rec601 penaliza el azul → para lluvia azulada ajustar luma_weights/gamma en el matting. Probado e2e en GPU con SD1.5 — heavy rain on_black seed 11 1024×576 (16:9 exacto), estrías de lluvia brillantes sobre negro plano (esquinas luma 0.00, dark 89.6%, lluvia 1.4% brillante) apto luma→alpha aditivo (prompt_id 5d2300d1, reports/0176). SD1.5/SDXL. |
comfyui_build_rune_glyph_workflow_py_ml |
(glyph, *, glow=True, style="arcane glowing rune", checkpoint="dreamshaper_8…", size=512, seed=0, lora=None, …) -> dict |
UNA runa / glifo / sigilo mágico (glifos rúnicos, círculos mágicos, sigilos de invocación, inscripciones brillantes) para hechizos, portales, marcas de conjuro y efectos de magia: símbolo arcano aislado sobre fondo uniforme ({glyph}, {style}, magic symbol, single isolated glyph, centered, glowing on a solid pure black background, occult sigil, arcane inscription, no scenery, game asset…) → txt2img cuadrado + LoRA estilo opcional. glow elige el camino a alpha: glow=True (defecto) = runa BRILLANTE sobre NEGRO puro, sin Rembg (recortaría el halo del resplandor), insumo de comfyui_matting_luma_to_alpha (luma=alpha, blend aditivo en el motor — conserva el glow); glow=False = runa MATE/grabada sobre fondo plano (el negativo rechaza glow/neon/bloom), recorte/inversión por el caller. El negativo rechaza realistic text/readable words/latin alphabet (un glifo arcano, no letras reales) + fondo texturizado/niebla. DISTINTO de status_effect_icon (símbolo SÓLIDO de UI, recorte Rembg, legible a 16-32 px en el HUD): la runa es una marca translúcida que emite luz e se inscribe en el mundo. Grimorio coherente = mismo style/checkpoint/lora, varía glyph/seed. ⚠️ luma Rec601 penaliza el rojo → para runas rojas (sigilo demoníaco) pasar luma_weights con más peso al rojo + subir gamma; runas blancas/azules/doradas van con pesos por defecto. Probado e2e en GPU con SD1.5 — circular summoning rune glow seed 11 512×512, círculo de invocación brillante sobre negro puro (esquinas luma 0.00, dark 83%, runa 3.4% brillante, max 255) apto luma→alpha (prompt_id 701d149a, reports/0172). SD1.5. |
comfyui_build_title_lettering_workflow_py_ml |
(text, *, letter_style="epic fantasy metallic", checkpoint="juggernaut_xl_v11…", width=1024, height=512, transparent=True, seed=0, lora=None, …) -> dict |
EL texto/logo de título de un juego (el nombre del juego o una palabra) renderizado con un tratamiento de lettering (metálico, tallado en fuego/piedra/madera, neón, cristal, oro), formato apaisado (width>height, 1024×512 por defecto), fondo plano recortable a alpha (the word "{text}" as a game logo, {letter_style} lettering, stylized typography, centered, plain background…) → txt2img apaisado + LoRA estilo opcional + Rembg (alpha). El negativo NO rechaza texto (el lettering es el sujeto) y empuja contra el ruido textual (extra letters/jumbled text/deformed letters). El VALOR es el ESTILO del lettering, NO la fidelidad tipográfica: ⚠️ la difusión renderiza texto de forma imperfecta — letras de más, deformadas o mal escritas; mitigar con palabras CORTAS en MAYÚSCULA, re-roll de seeds (comfyui_batch_generate), SDXL > SD1.5 para texto, o pintar el texto real con una fuente en el motor. Una palabra que es un objeto concreto (DRAGON) → el modelo dibuja el objeto, no las letras — usar palabras abstractas o reforzar letter_style. Marca coherente = mismo letter_style/checkpoint/lora, varía solo text. Recorte por Rembg (logo sólido), no luma→alpha. Probado e2e en GPU: DRAGON/fire engraved SD1.5 1024×512 → ilustró dragones rojos (alpha OK, confirma el gotcha de palabra-objeto, prompt_id 6f3920b7); AETHER/epic fantasy metallic SDXL 768×384 → logo de texto metálico dorado legible con ortografía imperfecta + alpha (prompt_id 2a7fe8ba, reports/0165). SD1.5/SDXL. |
Builders de transformación (gamedev-2d, puros — parten de una imagen/dibujo de entrada)
A diferencia de los builders de generación de arriba (parten de TEXTO, txt2img desde ruido), estos parten de una imagen de entrada y la transforman. Dos sub-ejes:
- img2img (
asset_variant): parte de un asset ya pintado; el KSampler arranca del latente de la imagen base (LoadImage → VAEEncode), no de ruido, así que condenoisemedio conserva la estructura mientras el prompt reescribe material/paleta/tier. Conserva forma y color del original. - sketch→ControlNet (
sprite_from_sketch): parte del dibujo tosco del dev (boceto, lineart, garabato); estxt2img(arranca de ruido) pero condicionado por un ControlNet atado al mapa de líneas del dibujo. Conserva solo la forma; la IA pone material/color/acabado.
Cubren el eje que el critic de generación (reports/0178) no exploró: derivar de un asset o
del dibujo del dev, no inventar un tipo nuevo desde texto.
| ID | Firma corta | Qué hace |
|---|---|---|
comfyui_build_asset_variant_workflow_py_ml |
(input_image, variant, *, checkpoint="dreamshaper_8…", denoise=0.5, style="game asset", size=512, seed=0, lora=None, …) -> dict |
UNA variante coherente de un asset 2D ya generado (img2img): parte del sprite/icono que existe en input_image y produce su versión de otro material/paleta/tier/estado (ice element, fire element, battle-damaged, golden tier 2, corrupted) manteniendo silueta, pose y composición del original. Compone comfyui_build_img2img_workflow (LoadImage → VAEEncode → KSampler con denoise) + comfyui_inject_lora (estilo opcional) + ImageScale opcional (size normaliza la base a size×size; size=None preserva las dimensiones exactas sin deformar). El prompt es {variant}, {style}, same composition, same pose, same silhouette, …. denoise es la palanca: ~0.3 invisible, 0.45-0.6 recomendado (cambia material/paleta, conserva forma), ~0.8 deriva la pose y se acerca a txt2img. Set de variantes del MISMO asset = mismo input_image/style/seed, varía solo variant. DISTINTO de los builders txt2img (enemy_creature, item_icon…): esos generan un tipo desde cero; éste transforma uno concreto. NO inyecta Rembg (img2img preserva el fondo/alpha del original según la base). ⚠️ la imagen base debe existir en input/ del server (subir con POST /upload/image); pura, no valida (usar comfyui_validate_workflow antes de enviar); asset NO cuadrado + size fijo + crop="disabled" deforma → size=None o crop="center". Probado e2e en GPU con SD1.5 — variante ice element, frozen del goblin enemy_creature_00001_.png denoise 0.5 seed 7 512×512 (prompt_id 5e4a5d3d): silueta conservada (luminance corr 0.63) + paleta a frío (blueness B−R −1.6→+1.9), reports/0181. SD1.5. |
comfyui_build_sprite_from_sketch_workflow_py_ml |
(sketch_image, subject, *, control_type="lineart", checkpoint="dreamshaper_8…", style="game asset, clean, centered", strength=0.8, size=512, seed=0, lora=None, preprocess=True, controlnet_name=None, …) -> dict |
UN sprite pintado a partir del BOCETO del dev, guiado por ControlNet (sub-eje sketch→ControlNet, NO img2img). Recibe el dibujo tosco que existe en sketch_image (boceto/lineart/garabato) + subject (qué es), y genera un sprite en estilo de juego que conserva la forma dibujada: el dev marca la silueta, la IA pone material/color/acabado. Mecanismo: txt2img base (ruido, EmptyLatentImage, denoise 1.0) cuyo positivo pasa por ControlNetApply atado al mapa de líneas del boceto. control_type elige el preprocesador (LineArtPreprocessor / ScribblePreprocessor / CannyEdgePreprocessor, interpuesto entre el boceto y el ControlNet por un helper) y, por defecto, el modelo CN emparejado. Compone comfyui_build_txt2img_workflow + comfyui_inject_controlnet + comfyui_inject_lora (estilo opcional). strength es la palanca: 0 = ignora el dibujo (txt2img puro), ~0.8 recomendado (respeta forma dejando limpiar a la IA), 1.0 = se ciñe estricto. DISTINTO de asset_variant (img2img conserva forma+color de una imagen ya pintada) y de los txt2img (enemy_creature…, inventan la forma desde texto): éste conserva solo la forma del dibujo. ⚠️ el boceto debe existir en input/ (subir con POST /upload/image); pura, no valida (usar comfyui_validate_workflow antes de enviar); preprocess=False solo si el sketch ya es un lineart limpio. GOTCHA del server 8GB: solo canny/depth/openpose SD1.5 instalados — para lineart/scribble pasa controlnet_name="control_v11p_sd15_canny_fp16.safetensors" u usa control_type="canny" (out-of-the-box); pendiente humano descargar control_v11p_sd15_lineart_fp16/scribble. Probado e2e en GPU con SD1.5 — boceto del goblin enemy_creature_00001_.png → CannyEdgePreprocessor → ControlNet canny, subject="dark fantasy goblin warrior" strength 0.85 seed 123 512×512 (prompt_id ea6fc372): pose/orejas/hombrera/lanza dentada/espada del dibujo conservadas, repintado en estilo de juego, reports/0182. SD1.5. |
Funciones de post-proceso y puente (gamedev-2d, 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. |
Pipelines one-shot (gamedev-2d, impuros)
| ID | Firma corta | Qué hace |
|---|---|---|
comfyui_generate_asset_pack_oneshot_py_pipelines |
(pack, *, checkpoint="dreamshaper_8…", style="", lora=None, base_seed=0, size=None, server="127.0.0.1:8188", export_godot=None, out_dir=None, …) -> dict |
Set COHERENTE de assets 2D de un mismo juego de un solo tiro: pack=[{"kind","subject"}, …] → despacha cada kind a su builder atómico (26 kinds: item_icon, enemy_creature, prop_object, seamless_tile, ui_hud, particle_texture, …) compartiendo el MISMO checkpoint/lora + style común inyectado al subject + seed = base_seed + i, encola (submit) + espera (wait) + descarga (fetch) cada uno, y (si export_godot) los exporta a Godot. Promoción a pipeline del patrón "N builders con el mismo estilo" (issue 0087). Fail-fast si kind desconocido; un OOM aislado no aborta el resto. Probado e2e en GPU SD1.5 512: magic sword(item_icon, seed 42) + goblin warrior(enemy_creature, seed 43), style="dark fantasy, hand-painted" → 2/2 PNG 512×512 RGBA coherentes (prompt_id f7cfda43 + 11d1d031, reports/0179). Impuro: HTTP + disco + (export) subprocess. |
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): el
set coherente ya está promovido —
comfyui_generate_asset_pack_oneshotgenera un pack entero compartiendo checkpoint/style/lora/seed (issue 0087, ver tabla de pipelines arriba). One-shots por-asset individuales (pixelart/sprite/VFX) siguen encadenándose a mano; candidatos a promoción 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.