Calcomanías de ajolote
Todo es Python puro (numpy + Pillow) más ffmpeg; sin GPU, sin Blender. La raíz del repositorio es la carpeta que contiene engine/, kit/ y out/.
pip install numpy pillow # ffmpeg debe estar en PATH
python engine/build.py 301 --force # renderizar una especificación (por id)
python engine/build.py 12,40-45 --force # varias
python engine/build.py # todo lo que aún no está renderizado (reanudable)
python engine/sheet.py 301-310 # hoja de revisión -> ref/sheet_sel_N.png (portada + 3 fotogramas cada una)
python engine/manifest.py # actualizar out/stickers.json después de añadir stickers
python engine/tornado.py 我没事 # el sticker de tornado de agua ("-" = sin texto); necesita engine/fetch_mc.py primero
Salida: out/NNN_文字.gif y la portada out/_封面/NNN_文字.png.
Añadir un sticker
Una línea por sticker en engine/specs.py (agregar al final de la sección correspondiente para que los ids existentes se mantengan estables):
S('摸鱼', 'flagwave', 'happy', [], hold='fish', s=0.7)
# texto movimiento cara fx extras
S('别催了', 'rage', 'angry', ['steam'], style='red', tmode='shake')
S('暴富', 'spin', 'money', ['coins', ('float', 'money', 3, 4)], style='gold')
Elige el movimiento que represente la frase, luego una cara, 0–2 efectos, y como máximo un prop/gorro. Mantén el texto de 2 a 5 caracteres (6 o más se divide en dos líneas y se vuelve pequeño). Usa / para forzar un salto de línea.
- movimiento (
engine/motions.py,engine/motions2.py, 75 en total): nod shake hop jump flip spin sink popup peek hide tremble rage tantrum dance wag bow kowtow doze flop melt dash slidein look lookup wave cheer clap belly flipover float zoom pounce approach tilt shrink puff grow drift buoy sway headbang headbob roll circle stare shy turnaway think boing wobble faint run launch stretch slosh petrify glitch squish hiccup shakeoff nuzzle rise recoil bonk, y acciones de props swing flagwave offer chomp drink read typing scan umbrella (estas leenhold=). - cara (
FACESen motions.py): normal smile happy joy love star shock surprise angry rage sad cry sob teary sleep sleepy tired meh dead dizzy smug wink focus struggle blep drool money awkward side cool eat shy tiny up grin catface blank pout sparkle determined worried xd — o un dict como{'L': 'big', 'R': 'big', 'mouth': 'o'}. - fx (
engine/fx.py): hearts question exclaim shock anger sweat panic zzz notes tears stream rain bulb confetti fireworks stars steam gloom sparkles speed fire sun moon blush coins snow leaves check cross boom bubbles ghost dots loading bolt flash thumb plus1 flowers swirl skull twinkle brokenheart; los genéricos toman un nombre de icono:('float', 'diamond', n, size),('pop', 'pin', size, (dx, dy)),('stay', 'clock', size, (dx, dy)),('say', 'mail'),('orbit', 'star', n, (rx, ry), size),('fall', 'flower', n, size). - hold= (prop voxel sostenido): pickaxe sword wrench flag fish rod heart diamond emerald cookie apple melon carrot potion bulb book cup boba phone laptop gift cake tnt grass brick bowl popcorn torch rtorch magnifier mail key trophy controller bucket umbrella …
- wear=[…] (gorros/accesorios faciales): party crown nightcap shades glasses band helmet halo horns phones bow chef grad flowers mask towel ice
- style= color del texto: pink (predeterminado) blue purple red green gold gray cyan — que coincida con el estado de ánimo (triste azul, enojado rojo, dinero dorado, hecho verde, cansado gris, noche púrpura).
- tmode= animación del texto: stay (predeterminado) wave bounce shake shiver pulse droop swing zoom spin pop type slam.
Revisa antes de entregar cualquier cosa
Renderiza, luego abre la hoja de revisión y mírala realmente. Verifica que:
- la portada (primer fotograma) muestre el texto completo y el ajolote;
- el prop/efecto se vea al tamaño del sticker y no esté oculto detrás de la banda de texto (todo lo que esté encima de la cabeza comparte espacio con el texto);
- el fondo blanco se haya mantenido blanco (el exportador reintenta con una paleta de fotograma completo cuando ffmpeg lo tiñe);
- el archivo sea ≤ 1000 KB (el exportador reduce de 64 a 24 colores automáticamente).
Problemas comunes
- Los movimientos que salen del fotograma durante el bucle (launch, sink, dash, popup, slidein, glitch) no deben usar texto
pop/slam/type— la portada capturaría al ajolote fuera de la pantalla. - Demasiados stickers con el mismo movimiento se siente repetitivo: mantén cualquier movimiento a unas 6 usos en el conjunto (
python -c "import sys; sys.path.insert(0,'engine'); import specs, collections; print(collections.Counter(s['motion'] for s in specs.all_specs()).most_common(10))"). - Las patas delanteras son pequeñas y están debajo de la cabeza; los gestos solo con patas apenas se leen — combínalos con un prop o un efecto.
- Las coordenadas de los props son píxeles del modelo local a la cabeza: la cara está en z = -10, la parte superior de la cabeza en y = 9, +x es la izquierda del espectador.
- El humor que funciona con esta audiencia es serio (难绷), no gritos exagerados.
El tornado de agua
engine/tornado.py dibuja el embudo como la misma masa de agua que el estanque (un contorno, mismo color, la línea blanca del agua sube por las paredes), hace girar bandas en espiral, lanza gotas y tumba al ajolote en 3D junto con objetos de Minecraft vanilla hechos 3D (casco de hierro/tortuga, cubo de ajolote, TNT). Ejecuta python engine/fetch_mc.py una vez para copiar esas texturas desde tu propio cliente de Minecraft (jar 1.21.2+) — nunca se confirman.