Sprites. Animaciones en 2D. 1

Motor de juego

Como ya comentamos en el artículo «Screen, pantalla o escena. Visualización gráfica», tanto los videojuegos como los entornos de realidad virtual se dividen en pantallas llamadas escenas o screens. En este artículo vamos a centrarnos en el mundo de las dos dimensiones, 2D. Vamos a tratar sobre sprite de imágenes.

Zelda

Los sprites o duendecillos fueron definidos por Jay Miner, de la compañía Atari, como mapas de bits o bitmap utilizados para la representación visual. Los sprites contienen la información gráfica de un objeto. Una escena está compuesta por uno o varios sprites que se añaden al surface que controla el «pintado».

Una imagen suele componerse por la suma de los bits de tres canales, rojo, verde y azul, rgb (por las iniciales en ingles en Big Endian) o bgr (Little Endian) según el formato de lectura. Cada canal está compuesto por valores con un tamaño de un byte (8 bits) cada uno. Por lo tanto, un pixel queda definido por una tonalidad de entre 255 por cada color primario (255 255 255). Si todos los colores tiene valor 255, obtenemos blanco y si son 0, negro. Posteriormente se le añadiría un cuarto canal llamado alpha, rgba o bgra. Este cuarto canal se utiliza para transparencia y efectos.

Con el tiempo, las tarjetas gráficas de los PCs fueron ganando en capacidad de resolución, por lo que la paleta de colores aumentó considerablemente. De esta forma la cantidad de bits usados para definir el color de cada uno de los canales aumentó. Existen capacidades de color, o «profundidad» de 8, 16 y 32 bits. El termino profundidad viene heredado de la forma de definir los modos de vídeo o resoluciones de una pantalla. Están compuestos por la cantidad de pixels que es capaz de pintar a lo largo y ancho de la pantalla y los bits por color. Una resolución muy común en los juegos de arcade es 800x600x8. Si comparamos este formato con el de las medidas de por ejemplo un mueble, XxYxZ, la profundidad o Z se correspondería con los bits de color.

Por lo tanto, todos los objetos que se deseen añadir a una pantalla deben tener un sprite asociado. Existen diferentes tipos de sprites definidos. Hay algunos básicos como buttonsprite, animatedsprite, textsprite, etc. Estos dependerán del motor de juego con el que estemos trabajando. El resto, suelen ser herencias de los anteriores.

Goomba

La potencia de los sprites que se pueden procesar como bits por capas. De esta forma, si queremos eliminar un color, modificar otro o realizar una transparencia o mezclado (blender), solo tenemos que añadir una mascara. Si queremos cambiar la imagen en caliente para pasar a otro frame de una animación, solo tenemos que desplazar el buffer de memoria sobre la imagen tantas posiciones como nos indique el alto y el ancho de los sprites. Si queremos desplazar el objeto, solo tenemos que modificar el puntero que hace referencia al origen de coordenadas.

Otro de los puntos fuertes de los sprites es la poca carga en memoria gráfica, ya que solo necesitamos cargar los pixeles de la imagen. Por contra, todos los procesos que se realizan sobre los sprites se procesan directamente en la CPU, lo que supone una fuerte dependencia hardware. En el caso de los modelos 3D muchas de las rutinas se realizan en las propias tarjetas gráficas.

Por lo tanto los sprites son muy potentes y sencillos de manejar, dando al desarrollador una amplia gama de acciones que realizar sobre ellos. Aunque hay que ser cuidadoso y no sobrecargar las escenas pues perderíamos ciclos de pintado y ralentizaríamos el juego.

Los acciones más importantes que se realizan sobre los sprites son:

    • Animación: Cuando nos encontramos ante un sprite que va a representar un movimiento, se genera mediante la reproducción de una tira de imágenes. Al igual que cuando vamos pintando en la esquina de un taco de postits un muñeco que se va moviendo y posteriormente raspamos dicha esquina con nuestro dedo para que los posits se vayan pasando y visualmente el muñeco se «mueva». En una tira de imágenes colocamos en sucesión las diferentes posturas que componen el movimiento del sprite. Cada imagen debe de estar contenida en una caja imaginaria de las dimensiones de dicho sprite. Cada caja se corresponde con un frame de la animación.

      Tira animada. Algunas imágenes pueden contener más de una animación.

      Cuando realizamos el refresco de la imagen de la pantalla el manejador de sprites desplazará el buffer de pintado del sprite al siguiente frame de la animación, creando la sensación de movimiento.

    • Traslación: Cuando un objeto se desplaza por la pantalla, ya sea de una forma programada o por instrucciones de los periféricos, la nueva posición es el resultado de una transformación mediante una matriz de coordenadas aplicada al punto de origen donde se va a empezar a «pintar» el sprite. Este origen de coordenadas suele coincidir con el punto superior izquierdo de la imagen o frame (top-left).
    • Rotación: De la misma forma, si queremos realizar una rotación de los sprites, recurriremos a las partes angulares de la matriz de transformación aplicada al sprite.
    • Escalado: Podemos realizar un escalado proporcional en alto y ancho a una imagen mediante la componente «peso» de la matriz de traslación. Estos escalados suelen definirse mediante porcentajes siendo 100% la imagen real, 50% la mitad y 200% el doble. El escalado puede hacerse de forma directa o lineal, como por ejemplo la representación de los latidos de los corazones de vida en un juego de plataformas.
  • Transparencia: En las arquitecturas que trabajan con rgb o bgr, para eliminar las partes de la imagen que no se deberían pintar (la parte que no se corresponde con el personaje), se pintaba el fondo de un color y se eliminaba de la paleta. Por ejemplo, era muy común utilizar el color magenta (255 0 255) o el verde claro (0 255 0) y los pixels con esa tonalidad no pintarlos.

    Imagen con diferentes sprites y fondo magenta.

    Con la inclusión del canal alpha, se añade otra capa de bits que actúa como máscara a la hora de pintar. Los pixels blancos se pintan, los negros no y con los grises podemos hacer mezclas o blender en arquitecturas más avanzadas.

En la actualidad los motores gráficos permiten la adición en caliente de sprites o assets desde scripts o factorías, las arquitecturas dedicadas a 2D suelen ser más estáticas en ese aspecto. Todos los sprites que van a componer una pantalla han de ser añadidos a las listas de sprites de cada escena en la carga del juego.  Los sprites se añaden a las listas de assets junto con su tipo y las características necesarias para su correcta utilización. Flags, coordenadas, altura, anchura, número de frames, son algunas de las características genéricas. Otras pueden depender de la API de renderizado que se vaya a utilizar. Después, en ejecución, cada tipo de sprite gestionará si ha de pintarse o no haciendo blit o blitting con las herramientas de la API para añadirse al buffer correspondiente a la memoria gráfica.

Aunque estas pixeladas imágenes parecen recuerdos de las máquinas de arcade en la actualidad siguen utilizándose y no solo en videojuegos. La potencia y versatilidad del mapa de bits y la poca carga en memoria que suponen frente a los modelos 3D hacen que sea difícil darlos de lado e incluso que sean la base de nuevas arquitecturas como la de las webs programadas sobre HTML5. Por ejemplo la plataforma Quintus creada para la creación de juegos en red con HTML5 y JavaScrips, trabaja con sprites en 2D.

Referencias:


Deja un comentario

Una idea sobre “Sprites. Animaciones en 2D.