Personajes con SVG por partes
Dibuja un personaje en Inkscape con un id por parte y anímalo con part, with_pivot y look_at
Dibujar en un editor, animar por partes
Un personaje ilustrado se dibuja mejor en un editor vectorial que con curvas escritas a mano. En esta guía lo dibujas en Inkscape (vale cualquier editor que guarde SVG), le das un id a cada parte que quieras mover y lo animas en Gaanim: inclinas la cabeza desde el cuello, levantas las cejas, saludas con un brazo y haces que el otro apunte a un objeto que se mueve.
Prepara el SVG
- Dibuja cada parte móvil por separado: cabeza, cejas, brazos, piernas. Agrupa (
Ctrl+G) lo que se mueve junto, como la cara con sus ojos. - Dale a cada parte un
iden Objeto › Propiedades del objeto (Ctrl+Shift+O): escribe el nombre en ID y pulsa Establecer. Usa nombres cortos sin espacios (cabeza,brazo-der); distinguen mayúsculas. - Dibuja las extremidades en reposo y extendidas a lo largo del eje x, desde la articulación hacia fuera. Así un giro de 0 es la pose de reposo y
look_atapunta la extremidad hacia su objetivo. - Si una parte tiene que girar entera hacia un objetivo con
look_at, haz que sea un solo trazado (Trazo › Unión): en un grupo,look_atgira cada miembro por separado. - Guarda como SVG plano. Anota en píxeles los puntos de giro: el cuello, los hombros, las caderas.
El personaje de esta guía (assets/personaje.svg, 400 × 300 px) tiene las partes cabeza, cejas, ojos, nariz, boca, torso, piernas, brazo-izq y brazo-der; cada brazo es un solo trazado con su mano.
De píxeles del SVG a la escena
Gaanim importa el SVG a 100 píxeles por unidad, con el centro del documento en el origen y la y hacia arriba. Un punto (px, py) de un documento de ancho × alto píxeles, escalado por ESCALA, queda en
((px - ancho / 2) / 100 * ESCALA, (alto / 2 - py) / 100 * ESCALA)Usa with_pivot(0, 0) antes de scale_to, para que el SVG escale desde el centro del documento y la fórmula siga valiendo. Con ella fijas el pivote de cada parte en su articulación.
Animar por partes
part(id) devuelve cada parte como un Drawable propio: se anima, se colorea y se mueve sin mover el resto. with_pivot fija el punto alrededor del que gira:
from gaanim import GOLD, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
ESCALA = 2.0
persona = scene.media.svg("assets/personaje.svg").with_pivot(0, 0).scale_to(ESCALA)
def punto(px, py):
"""Un punto del SVG, en píxeles, en coordenadas de la escena."""
return ((px - 200) / 100 * ESCALA, (150 - py) / 100 * ESCALA)
cabeza = persona.part("cabeza").with_pivot(*punto(200, 140)) # el cuello
cejas = persona.part("cejas")
brazo_izq = persona.part("brazo-izq").with_pivot(*punto(164, 159)) # hombro izquierdo
brazo_der = persona.part("brazo-der").with_pivot(*punto(236, 159)) # hombro derecho
scene.play([persona.animate.fade_in().duration(0.4)])
# Inclina la cabeza, levanta las cejas y saluda.
scene.play([
cabeza.animate.rotate_by(0.15).duration(0.4),
cejas.animate.shift_by(0, 0.08).duration(0.4),
brazo_izq.animate.rotate_by(-0.8).duration(0.4),
])
scene.play([
cabeza.animate.rotate_by(-0.15).duration(0.4),
cejas.animate.shift_by(0, -0.08).duration(0.4),
brazo_izq.animate.rotate_by(0.8).duration(0.4),
])
# El brazo derecho sigue a la estrella mientras se mueve.
estrella = scene.geometry.star(5, 0.3, 0.12).fill(GOLD).move_to(5, 3)
brazo_der.look_at(estrella)
scene.play([estrella.animate.move_to(5, -2.5).duration(1.2)])
scene.render()
look_at sigue al objetivo desde el cursor hasta clear_drive(); con offset= (radianes) sirve también para partes dibujadas apuntando a otro lado, como un brazo izquierdo extendido hacia la izquierda (offset=math.pi).
Trazos que crecen con la cara
Las cejas, la nariz y la boca de este personaje son trazos. Un trazo mide su ancho en unidades de escena, así que al agrandar la cabeza quedarían más finos que el resto. scale_stroke_with_object() hace que crezcan con ella:
cabeza = persona.part("cabeza").with_pivot(0, 0.2).scale_stroke_with_object()
scene.play([cabeza.animate.scale_to(1.18).duration(0.5)])Referencia
- Medios:
scene.media.svg,partyparts. - Drawable:
with_pivot,look_at,scale_stroke_with_objecty las animaciones de.animate. - Movimiento: trayectorias, updaters y temblores para dar vida a un personaje quieto.
- Layout:
scene.layout.scatterreparte fórmulas o etiquetas alrededor del personaje sin tapar sus partes (avoid=[persona.part("cabeza"), ...]).