12-Sprites (III)

Recordar que todo esto están basados en los ejemplos del SGDK,
carpeta sample > sprite

 

Aventuras en Megadrive: Sprites (III)

Vamos a animar a Sonic. Esta es la hoja de sprites de Sonic, sonic.png en carpeta RES:

sonic

Cada fila define una animación completa. Podemos tener hasta 16 filas.
Si poPara referirnos a una fila en concreto pondremos:

#define ANIM_STAND 0
#define ANIM_WAIT 1
#define ANIM_WALK 2
#define ANIM_RUN 3
#define ANIM_BRAKE 4
#define ANIM_UP 5
#define ANIM_CROUNCH 6
#define ANIM_ROLL 7

Después, dentro del código, utilizaremos la función

SPR_setAnim(sprite, animacion);

Por ejemplo, si cambiamos esta función en el programa del post anterior…

[..]
static void handleInput()
{
  //variable donde se guarda la entrada del mando
  u16 value = JOY_readJoypad(JOY_1);
  //si pulsamos izquierda...
  if (value & BUTTON_LEFT)
  {
    SPR_setPosition(mi_sonic, posx--, posy);
    SPR_setHFlip(mi_sonic, TRUE);
    SPR_setAnim(mi_sonic, ANIM_RUN);
  }

  //si pulsamos derecha...
  if (value & BUTTON_RIGHT)
  {
    SPR_setPosition(mi_sonic, posx++, posy);
    SPR_setHFlip(mi_sonic, FALSE);
    SPR_setAnim(mi_sonic, ANIM_RUN);
  }

  //si no pulsamos
  if ((!(value & BUTTON_RIGHT)) && (!(value & BUTTON_LEFT)))
  {
    SPR_setAnim(mi_sonic, ANIM_STAND);
  }
}
[..]

No olvides poner al principio del archivo, tras los includes, los defines que pusimos al principio del post.

Además he usado otra función para espejar los sprites.

SPR_setHFlip(sprite, TRUE | FALSE );

Y he puesto que, si no se detecta que pulsamos DERECHA o IZQUIERDA, el sprite cambia también, para que no se quede quieto con el gráfico de correr.

Ya va cogiendo el aspecto de un juego.

 

ENEMIGOS

En la carpeta RES / Sprite tenemos el archivo enemies.png:

enemies

Al contrario que en el ejemplo de Sonic, tenemos sprites para dos enemigos distintos. Ambos en el mismo archivo. Este es el archivo sprite.res:

SPRITE sonic_sprite “sprite/sonic.png” 6 6 FAST 5
SPRITE enemies_sprite “sprite/enemies.png” 6 4 FAST 5

En el mismo archivo definimos el sprite de Sonic y de sus enemigos.

Tanto la avispa como el cangrejo tienen misma forma rectangular de 6×4 tiles, sólo tienen una animación así que usamos el mismo nombre enemies_sprite para ambos. Usaremos un array para referirnos a ellos.

enemies_sprite[0] será la avispa  y enemies_sprite [1] será el cangrejo

Obviamente para enemigos más complejos, con más animaciones o distintas formas, tendremos que añadir diferentes líneas en el archivo RES.

Por tanto pondremos antes del main:

//Enemigos
Sprite* enemigos[2]; 

//Posición en pantalla de los enemigos
u32 enemigoPosx[2];
u32 enemigoPosy[2];

Ya dentro del main, antes del loop principal:

//añade los enemigos

//posicion
enemigoPosx[0] = 128;
enemigoPosy[0] = 164;
enemigoPosx[1] = 260;
enemigoPosy[1] = 84;

//recoje la paleta de los enemigos y la mete en la 4a paleta del sistema
VDP_setPalette(PAL3,enemies_sprite.palette->data);

//sprite
enemigos[0] = SPR_addSprite(&enemies_sprite, enemigoPosx[0], enemigoPosy[0], TILE_ATTR(PAL3, TRUE, FALSE, FALSE));
enemigos[1] = SPR_addSprite(&enemies_sprite, enemigoPosx[1], enemigoPosy[1], TILE_ATTR(PAL3, TRUE, FALSE, FALSE));

//asigna la animacion correcta (o todos tendrán la primera animación del fichero png)
SPR_setAnim(enemigos[0], 1); //asigna la animacion del cangrejo (la segunda, 1, del png)
SPR_setAnim(enemigos[1], 0); //asigna la animacion de la avispa (la primera, 0, del png) <- no es necesaria

SPR_update(); // <- no es necesaria pero recomendable

Está bastante claro pero hay varias cosas a comentar.

En primer lugar los SPR_addSprite(). Esto asigna al primer y segundo enemigo el sprite y les da posición. Pero NO distingue qué sprite/animación del archivo PNG coge. Por defecto ambos tienen el mismo, el primero, la avispa.

Por eso a continuación usamos los SPR_setAnim() para asignar al cangrejo su sprite correcto. El de la avispa no es necesario (ya lo tiene), pero ponerlo da claridad al código (sobretodo si luego añadimos animaciones al PNG y hacemos cambios).

Queda como ejercicio borrar los SPR_setAnim (o comentarlos) y ver qué pasa.

De la misma forma el SPR_updated()  es buena costumbre ponerlo (para mandar la información al VDP). En este ejemplo no se nota su ausencia, es pequeño, en un proyecto serio hay que tenerlo todo a punto antes de entrar en el loop.

 

ENEMIGOS EN MOVIMIENTO

Los enemigos se moverán de un lado al otro de la pantalla. Al principio del código pondremos:

s16 enemigoSentidoMovimiento[2];

Valdrá 1 si el enemigo ha de moverse a la derecha, -1 a la izquierda.

La avispa comenzará moviéndose a la izq, el cangrejo a la derecha.

enemigoSentidoMovimiento[0] = 1;
enemigoSentidoMovimiento[1]= -1;

Ahora hay que definir una función que compruebe dónde están, si llegan a los extremos, se tienen que dar la vuelta.

..EN DESARROLLO..

Anuncios