¿Qué hace Boceto a tinta?
Dibuja una imagen como un SVG animado autónomo: líneas de tinta ondulantes de ancho variable, lavados de marcador ligeramente desplazados de las líneas, sobre papel crema. 2D plano, vista frontal o lateral. Las líneas "hierven" (la ondulación se redibuja cada 2 fotogramas), por lo que incluso un sujeto estático parece vivo, y la escena puede añadir un pequeño movimiento con t. Para una versión 3D, isométrica, usa la habilidad handdrawn-3d en su lugar. Las etiquetas y títulos usan una fuente de trazo dibujada a mano incorporada que cubre latín y vietnamita.
Kit: assets/kit.js · renderizador: assets/render.mjs · todas las funciones: references/kit.md (léelo antes de escribir una escena) · ejemplos trabajados: examples/ (taza, manzana, gato, planta, casa, comida).
Configuración (una vez)
La exportación a PNG/GIF necesita @resvg/resvg-js. Si render.mjs dice que falta, ejecuta npm install en la carpeta de esta habilidad. La salida SVG no necesita nada.
Antes de dibujar
- ¿Se puede dibujar? Si el sujeto es abstracto ("esperanza", "productividad", "la economía"), no dibujes algo vago. Dilo y sugiere una o dos escenas concretas que lo muestren ("un brote empujando a través de una grieta en el pavimento"), luego dibuja la que el usuario elija.
- Diagramas, gráficos, IU, botones, cosas interactivas: no es esta habilidad.
- Animación: el SVG siempre hace bucle (ebullición de líneas). Añade un pequeño movimiento que pertenezca al sujeto (vapor, un movimiento de cola, un parpadeo, hojas meciéndose) cuando encaje o cuando el usuario lo pida; de lo contrario, solo la ebullición es suficiente. Un SVG de un solo fotograma solo cuando el usuario pida una imagen fija (
--still).
Flujo de trabajo
- Partes y vista. Enumera las partes reales del sujeto y elige la vista: frontal o lateral. Una tetera: cuerpo, tapa, perilla, pico, asa, pie; vista lateral. Dibuja a partir de las partes reales (bordes, asas, tapas, tallos, tableros, baldosas), no una mancha genérica con un nombre.
- Esquema. Escribe una pequeña tabla en un comentario al principio de la escena: parte, llamada de forma, cuadro (x, y, w, h), color. El sujeto ocupa ~65–80% de la hoja, centrado, con espacio para respirar. La línea de suelo/mesa se sitúa aproximadamente al 80–88% hacia abajo.
- Dibuja de atrás hacia adelante en
scene.jscon el kit: sombra → cosas detrás → cuerpo principal → detalles encima → etiquetas. Prefiere las piezas ya hechas (k.cat,k.person,k.tree,k.house,k.window,k.leaf…) y cambia sus opciones en lugar de redibujarlas. Usak.turnedpara cualquier cosa redonda que se pueda tornear (tazas, ollas, jarrones, botellas, cuencos, lámparas). Usak.tubepara asas, tallos, colas, brazos y ramas. - Renderiza y mira:
Abrenode <skill>/assets/render.mjs scene.js -o out/scene.svg --png out/scene.png --thumb --gridout/scene.pngcon la herramienta de lectura y míralo. La superposición--gridimprime coordenadas para que puedas leer dónde están las cosas realmente. Mira tambiénout/scene-128.png: debe seguir reconociéndose como el sujeto a 128 px. - Corrige y vuelve a renderizar. Verifica:
- ¿Se reconoce como el sujeto de un vistazo, y a 128 px? Primero la silueta: si el contorno no dice "tetera", ningún detalle la salvará.
- Proporciones y superposiciones: las asas se unen a los cuerpos, las cosas descansan en el suelo, nada flota o se superpone mal.
- La luz viene desde la parte superior izquierda en todas partes (sombreado/rayado en la parte inferior derecha).
- Las etiquetas no se superponen al dibujo ni cruzan otras líneas.
Repite 4–5 hasta que esté bien (generalmente 2–4 rondas). Luego renderiza la final sin
--grid.
Nunca entregues sin haber mirado el PNG. Entrega el SVG (la imagen animada) y las rutas del PNG, y muestra el PNG. Si la escena se mueve, verifica también algunos fotogramas (consulta Animación).
Reglas de estilo
- Un solo aspecto: tinta + lavado de marcador plano. Sin textura ni granulado. Sin degradados, resplandores, sombras paralelas, desenfoque, trucos de opacidad o
<text>SVG (usak.text/k.label/k.title). No añadas SVG sin procesar. - Color: nombres de paleta (
red, coral, orange, ochre, yellow, sage, green, leaf, teal, sky, blue, navy, lilac, plum, pink, wood, brown, chocolate, grey, stone, charcoal, white, cream, sand, skin, tan). 3–5 colores por imagen más tinta. Cualquier hexadecimal se suaviza automáticamente, pero los nombres de paleta se ven mejor. - Sombreado:
shade: true(o 0.15–0.35) en volúmenes principales;hatch: trueen uno o dos objetos grandes como máximo. La luz siempre viene desde la parte superior izquierda. - Grosor de línea: contornos
'outline'(predeterminado), detalles internos'detail', marcas pequeñas y líneas de referencia'fine'. - Bonito y redondo: los animales y plantas son suaves y redondos, con cabezas grandes, ojos de punto y pequeños óvalos de rubor. Sin anatomía realista y afilada.
- Composición: un sujeto claro, centrado, ocupando la mayor parte de la hoja. Una sombra de suelo (
k.shadow) debajo de cualquier cosa que se sostenga sobre algo. - Texto: opcional
k.title(...)en la parte superior izquierda, más etiquetas cortas en minúscula en los márgenes (k.label) con líneas de referencia, colocadas en el espacio vacío del margen. Nunca cajas o globos de diálogo flotando sobre el dibujo. Escribe las etiquetas en el idioma del usuario. El vietnamita es totalmente compatible. - Hoja: 1000×1000 por defecto. Para escenas anchas usa
export const sheet = { width: 1200, height: 900 }.--transparentelimina el papel.
Plantilla de escena
// tetera, vista lateral. partes: cuerpo (torneado), tapa, perilla, pico (tubo), asa (tubo), sombra
export const sheet = { seed: 1 };
export function draw(k, t = 0) {
k.shadow(500, 820, 300, 34);
k.tube([[690, 540], [810, 520], [810, 650], [700, 710]], 34, { fill: 'teal' }); // asa (extremos ocultos por el cuerpo)
k.tube([[330, 640], [250, 560], [200, 470]], [60, 26], { fill: 'teal', shade: 0.3 }); // pico
const pot = k.turned([[150, 0], [230, 70], [250, 180], [210, 300], [170, 330]],
{ cx: 500, y: 480, fill: 'teal', hatch: true }); // cuerpo
k.ellipse(500, 480, 150, 22, { fill: 'teal', weight: 'detail' }); // tapa
k.blob(500, 445, 30, { squash: 0.8, fill: 'ochre' }); // perilla
k.label('la buena tetera', { x: 640, y: 300, to: [560, 440] });
}
Animación (siempre activa)
out.svg es un SVG animado en bucle por defecto: fotogramas cambiados por CSS, sin script, funciona en navegadores y etiquetas <img> (los renderizadores sin animación CSS muestran el fotograma 0). Las escenas reciben t ∈ [0, 1), un bucle. Mantenlo simple: como máximo una o dos cosas en movimiento (vapor, un movimiento de cola, un parpadeo, hojas meciéndose, humo) además del hervido de línea automático: la ondulación se redibuja cada 2 fotogramas, por lo que incluso un sujeto estático parece vivo. Haz que el movimiento se repita sin problemas con Math.sin(2 * Math.PI * t). Las piezas ya hechas aceptan t:
k.steam(x, y, { t }), k.cat(..., { animate: true, t }), k.person(..., { wave: true, t }).
node <skill>/assets/render.mjs scene.js -o out/scene.svg --png out/scene.png # SVG animado + PNG fijo
node <skill>/assets/render.mjs scene.js -o out/scene.svg --gif out/scene.gif # + GIF, funciona en todas partes
node <skill>/assets/render.mjs scene.js -o out/scene.svg --still # SVG de un solo fotograma
--frames 8 --fps 10 --boil 2 --gif-size 560
Verifica un GIF mirando algunos fotogramas: ffmpeg -i out/scene.gif -vf "select='not(mod(n\,3))',scale=300:-1,tile=4x1" -frames:v 1 out/frames.png (o verifica el PNG fijo, que es el fotograma 0). Los GIF son de 256 colores: mantenlos a ≤ 600 px de ancho.