Registrarse

[Decomp-GBA] Animación Pokémon al "estilo Blanco y Negro" en pokeemerald

Thorec_A_C

Héroe de WaH
Haciendo limpieza en el PC me he encontrado con esto, que viene del siguiente post, más de un año y medio ha pasado, casi na... Total, que ya no me acordaba de ello y para que esté perdido para siempre pues lo publico aunque esté un poco a medias, por eso lo pongo en investigación y no en tutoriales.

La cuestión, esto es una manera de implementar animaciones de los Pokémon al “estilo Blanco y Negro” en decomp, concretamente en pokeemerald. Voy a explicarlo lo mejor que pueda, aunque aviso que no tengo grandes conocimientos con el código de decomp.

Esta implementación dista de mucho de ser profesional, salió un poco de ensayo y error, y presenta algunos bugs. Curiosamente estos bugs son los mismos que el famoso parche de BugMania para Fire red que recrea estas mismas animaciones.

Para empezar explicar que las animaciones de Esmeralda tienen 2 partes: una donde se cargan los frames de los sprites y se repiten x número de veces con x duración cada repetición; la otra que modifica los sprites dándoles efectos, un giro, estirarlos, etc.

Para empezar vamos a hacer que los frames se repitan indefinidamente para simular una animación continua como Blanco y Negro:

Vamos a: pokeemerald\src\data\pokemon_graphics\front_pic_anims.h

Aquí encontramos una función para cada uno de los Pokémon. La de Torchic por ejemplo es:

Código:
static const union AnimCmd sAnim_TORCHIC_1[] =
{
    ANIMCMD_FRAME(0, 7),
    ANIMCMD_FRAME(1, 4),
    ANIMCMD_FRAME(0, 4),
    ANIMCMD_FRAME(1, 4),
    ANIMCMD_FRAME(0, 4),
    ANIMCMD_FRAME(1, 4),
    ANIMCMD_FRAME(0, 10),
    ANIMCMD_END,
};
Donde ANIMCMD_FRAME(X, Y) indica cada repetición del frame, la X indica el ID del frame y la Y al duración.

Modificamos la función por esto:

Código:
static const union AnimCmd sAnim_TORCHIC_1[] =
{
    ANIMCMD_FRAME(0, 7),
    ANIMCMD_FRAME(1, 4),
    ANIMCMD_FRAME(0, 4),
    ANIMCMD_FRAME(1, 4),
    ANIMCMD_FRAME(0, 4),
    ANIMCMD_FRAME(1, 4),
    ANIMCMD_FRAME(0, 10),
    ANIMCMD_LOOP(1),
    ANIMCMD_JUMP(0),
    ANIMCMD_END,
};
Añadiendo loop y jump la animación pasa a ejecutarse indefinidamente. Debemos añadir esto para todos los Pokémon que queramos tengan esta animación.

Hay un problema con esto y es que al no finalizar nunca la animación el combate no continua. Sin embargo quitando los efectos de las animaciones que mencione antes, lo soluciona. Aunque hay una forma de mantener lo efectos con el loop no lo voy a poner porque acaba dando artefactos visuales en los combates, según mi experiencia, además se ejecutan sólo una vez al principio y queda raro con la animación continua.

Para ello vamos a: pokeemerald\src\pokemon_animation.c

Y cogemos cualquiera de las funciones de efectos disponibles en Esmeralda, por ejemplo cojo la de Unown, que es static void Anim_ZigzagFast(struct Sprite *sprite) y sutituyo todo por:

Código:
static void Anim_ZigzagFast(struct Sprite *sprite)
{
    sprite->callback = SpriteCallbackDummy;
}
Ya tenemos un efecto anulado así que ahora vamos a: pokeemerald\src\pokemon.c

Y asignamos esa función a todos los Pokémon que tengan animación continua en static const u8 sMonFrontAnimIdsTable[NUM_SPECIES - 1] =

Por ejemplo Bulbasaur quedaría así: [SPECIES_BULBASAUR - 1] = ANIM_ZIGZAG_FAST,


Con esto ya tendríamos implementado el sistema.

Ahora viene lo malo, hay 3 bugs con esto:
  1. Cuando accedemos al menú del equipo Pokémon o a la mochila en un combate, al volver a la escena de combate la animación no se ejecuta.
  2. Los cambios de stats y los efectos de algunos ataques como Fortaleza o Maldición dan errores gráficos.
  3. Al cambiar de Pokémon en un combate con un entrenador la animación del segundo Pokémon y los sucesivos no se inicia.

El primero de los bugs se como solucionarlo. Todos los créditos y agradecimientos van para kakarotto, otro usuario del foro que me ayudó a solucionarlo en su momento.

Para arreglar esto hacemos los siguiente:

En pokeemerald\include\battle_main.h añadimos al listado del principio:

void SpriteCb_WildMonAnimate2(struct Sprite *sprite);

En pokeemerald\src\battle_main.c añadimos:

Código:
void SpriteCb_WildMonAnimate2(struct Sprite *sprite)
{
    if (!gPaletteFade.active)
    {
        BattleAnimateFrontSprite(sprite, sprite->sSpeciesId, FALSE, 1);
    }
}
En pokeemerald\src\reshow_battle_screen.c añadimos al principio en el listado #include "battle_main.h"

Y luego en la función static void CreateBattlerSprite(u8 battler) indicamos en “gSprites[gBattlerSpriteIds[battler]].callback =” la función anterior quedando de la siguiente manera: gSprites[gBattlerSpriteIds[battler]].callback = SpriteCb_WildMonAnimate2;

Con esto se soluciona el primer bug que comenté.

Con respecto a los otros 2 no sé como solucionarlos, como comenté creo que también están presentes en el parche de BugMania. En este gif se pueden ver ambos bugs:



Para el error de los efectos visuales creo que la clave está en hacer que la animación pare mientras se realiza el efecto, en muchos ataques ya lo hace, se puede ver si implementáis esto, para unas décimas de segundo mientras se hace la animación del ataque. Habría que añadir esto a los ataques que dan error como Fortaleza o Maldición.

Con respecto a los cambios de estadísticas entiendo que habría que mirar en pokeemerald\src\battle_anim_utility_funcs.c pero no estoy seguro.

Y con el bug de los entrenadores no tengo ni idea, lo que investigué en su momento no me llevó a nada. Quizá algún experto en decomp que le interese este tema pueda aportar algo.

Por último comentar que si bien esto funciona con los sprites de Esmeralda, el resultado no es muy bueno ya que al usar sólo 2 frames las animaciones son bruscas. Sin embargo con 4 frames el resultado es bastante bueno. Importante, no usar más de 4 frames por Pokémon ya que según he leído supera lo que la memoria ram del juego en los combates puede soportar en combates dobles, aunque no estoy muy seguro de ello.

Ejemplo visual, animación con 2 frames:

2frames.gif


Animaciones con 4 frames:

4frames.gif

4frames2.gif


Otra cosa a tener en cuenta de esto es el espacio de la rom, ya que estamos metiendo el doble de frames por Pokémon.

Poco más tengo que añadir a esto. Espero que le sea de utilidad a alguien y si algún forero consigue solucionar los bugs y compartirlo con la comunidad le estaría muy agradecido.
 
Arriba