¡Bueeenaass!
Hoy os traigo un tutorial de los intensos, de los interesantes, de esos que sé que vais a utilizar casi seguro, porque vamos a conseguir dibujar sprites en absolutamente cualquier momento que nos propongamos, aunque con ciertos límites, pues a no ser que estemos cargando un escenario nuevo el cuál no use ni los minis ni sus paletas típicas etc, como bien digo, estaremos algo limitados y seremos propensos a tener bugs gráficos, y ojo, digo gráficos, porque en principio (a no ser que la liéis mucho) no afectará a la jugabilidad.
Aquí os muestro un ejemplo de lo que se puede hacer con este tutorial, un menú que hice usando regiones, cargando sprites y animándolos con dos métodos distintos (aunque esos dos tutos de animaciones tocan los próximos días)
Bien, una vez os he dejado aquí con todo el hype y con las ganas de aprender a usar esto, debéis saber una cosa, por increíble que parezca, yo tan sólo he usado una paleta, y aún así, he tenido algún error que otro, así que cuidado cargando sprites en el overworld.
Bien, nos dejamos de rollos y vamos con los requisitos, por cierto, si alguien tiene la duda de que es la OAM, aquí tenéis un post de cosarara en el que se abarcan bastantes cosas sobre ella.
Por cierto, antes de empezar me gustaría agradecer a Karakara, un usuario de un foro, que fue el que descubrió cuáles eran todos los parámetros que necesitaba un sprite para poder ser dibujado correctamente en la OAM, por tanto, créditos a él y un gran agradecimiento, si no fuera por él, probablemente no hubiera sido tan fácil conseguirlo, a pesar de ello, no tenía la investigación muy avanzada y la mayoría de los parámetros no estaban muy claros, pero por mi parte, tras haber creado este menú, entiendo CASI a la perfección que poner en cada uno de ellos, así que, empezamos.
Requisitios
He de decir que daré por hechas bastantes cosas, ya que no quiero hacer un tutorial demasiado extenso, pero sí que entraré a fondo en algunos temas que puedan causar confusión, aún así, si nuestro compilador nos tira un error, intentad leerlo e interpretarlo, que así es como se aprende.
¡Empezamos!
Y eso es todo, cualquier duda la podéis dejar por los comentarios, decidme que os ha parecido el post y un +Gracias se agradece
¡Chau!
Hoy os traigo un tutorial de los intensos, de los interesantes, de esos que sé que vais a utilizar casi seguro, porque vamos a conseguir dibujar sprites en absolutamente cualquier momento que nos propongamos, aunque con ciertos límites, pues a no ser que estemos cargando un escenario nuevo el cuál no use ni los minis ni sus paletas típicas etc, como bien digo, estaremos algo limitados y seremos propensos a tener bugs gráficos, y ojo, digo gráficos, porque en principio (a no ser que la liéis mucho) no afectará a la jugabilidad.
Aquí os muestro un ejemplo de lo que se puede hacer con este tutorial, un menú que hice usando regiones, cargando sprites y animándolos con dos métodos distintos (aunque esos dos tutos de animaciones tocan los próximos días)

Bien, una vez os he dejado aquí con todo el hype y con las ganas de aprender a usar esto, debéis saber una cosa, por increíble que parezca, yo tan sólo he usado una paleta, y aún así, he tenido algún error que otro, así que cuidado cargando sprites en el overworld.
Bien, nos dejamos de rollos y vamos con los requisitos, por cierto, si alguien tiene la duda de que es la OAM, aquí tenéis un post de cosarara en el que se abarcan bastantes cosas sobre ella.
Por cierto, antes de empezar me gustaría agradecer a Karakara, un usuario de un foro, que fue el que descubrió cuáles eran todos los parámetros que necesitaba un sprite para poder ser dibujado correctamente en la OAM, por tanto, créditos a él y un gran agradecimiento, si no fuera por él, probablemente no hubiera sido tan fácil conseguirlo, a pesar de ello, no tenía la investigación muy avanzada y la mayoría de los parámetros no estaban muy claros, pero por mi parte, tras haber creado este menú, entiendo CASI a la perfección que poner en cada uno de ellos, así que, empezamos.
Requisitios
- Tener ganas y no frustrarse a la primera
- Tener previamente instalado pokeruby (obviamente)
- Saber pasar archivos de .png a .gbapal y .4bpp, aquí el tutorial que creé sobre como hacerlo
- Nociones básicas de programación para no perdernos por el camino
- Character Maker Pro o cualquier otro programa que nos sirva para indexar, pero yo recomiendo este
He de decir que daré por hechas bastantes cosas, ya que no quiero hacer un tutorial demasiado extenso, pero sí que entraré a fondo en algunos temas que puedan causar confusión, aún así, si nuestro compilador nos tira un error, intentad leerlo e interpretarlo, que así es como se aprende.
¡Empezamos!
0.- Lo primero que necesitaremos, es tener nuestro archivo que indexaremos y guardaremos en .png, debéis pensar que la paleta debe estar ya acomodada tal y como la queremos, y que el color transparente deberá estar en primer lugar, tras tener todo listo e indexado, seguiremos el tutorial de gbagfx que os he dejado más arriba, para conseguir su archivo .gbapal y .4bpp (o .8bpp, etc, el que le corresponda, por lo general, .4bpp)
Aclarar que si estamos usando la misma paleta para varios iconos, o sprites, no tenéis que crear la paleta para cada uno de ellos, con crearla una vez y usarla para todos, sobra, obviamente.
1.- Ahora buscaremos el archivo .c en el que queremos que se cargue nuestro querido sprite y lo abrimos, o en caso de que queramos que sea un nuevo archivo, pues lo creamos, aunque si no sabéis como crear nuevos archivos .c, no lo hagáis.
2.- Por aquí os voy a ir dejando todo el código que un sprite siempre va a necesitar para que se pueda cargar, y voy explicándolos uno a uno.
(A partir de aquí, disculpad si no soy muy técnico, no estoy acostumbrado al entorno de C)
Con estos códigos estamos guardando la paleta y el sprite respectivamente en unas variables, y es muy importante, que tan sólo cambiéis donde dice "nombrePaleta" y "nombreSprite" por el que queráis y la ruta donde se encuentran. Decir que se pueden crear nuevas carpetas en graphics si lo deseáis, en este caso, la carpeta es una que creé yo para el menú.
También es muy importante que carguéis primero las paletas y luego los sprites.
3.-
Con entender que este código servirá más tarde para poder eliminar/destruir los sprites que creemos es suficiente.
4.-
Esta es la tabla de parámetros para la OAM que usaremos más adelante, id apuntando los nombres que le dais a cada cosa porque luego nos harán falta. Simplemente la editáis respecto a vuestras necesidades y listo.
He de decir, que si tenéis dos sprites con las mismas características, no creéis dos iguales, podéis usar el mismo para ambos (en este caso)
5.-
Estos simplemente son necesarios, usemos o no usemos animaciones, declaradlos y listo (y fijaos, que en la segunda función, se llama a la primera, por tanto, los nombres en verde oscuro deben ser los mismos)
Y ya tenemos todo lo que necesitábamos creando, por tanto, ahora tenemos que repetir este código con cada sprite que queramos cargar, y es totalmente obligatorio darle un nombre diferente a cada estructura.
ATENCIÓN.- Es muy importante crear cada estructura de forma manual, y repito, no crear dos estructuras con el mismo nombre, además, no deberíais crear una función constructora para pasar parámetros, puesto que esto me dio ciertos problemas, ya que "al salir de la función los datos se borran", y tiende a dar error visuales.
Como podéis comprobar, esta es la parte más importante, y donde se acumula todo aquello que hemos hecho con anterioridad.
Y como también podréis observar, os he señalado con negrita y colores los parámetros a los que debéis estar atentos, en este caso los colores naranjas corresponde a nombres que hemos declarado fuera o con anterioridad, y los azules son los que hemos declarado en el propio código. Sé que puede parecer algo exagerado ponerlo por colores, pero seguro que así lo veis más sencillo.
Debéis tener en cuenta que todos los parámetros que lleven "tag" como nombre, o como parte del nombre, no deben repetirse, me explico:
Por ejemplo, podemos crear la estructura de "SpriteSheet", "SpritePalette" y "SpriteTemplate" y usar en todas el número 12 como tag, pero teniendo en cuenta que estas estructuras van a corresponder al mismo Pokémon. Sin embargo, si creamos otras tres nuevas estructuras para otro icono, no debemos usar de nuevo el 12, si no cualquier otro número que no esté ocupado.
Y ahora, lo que todos estábamos esperando, cargar el sprite en pantalla, que lo haremos con esta serie de comandos:
En x e y, obviamente debéis colocar vuestras coordenadas, considerando que el punto (0,0) se encuentra en la esquina superior izquierda de la pantalla.
Es muy importante hacerlo en este orden, pues primer cargamos el SpriteSheet, luego el SpritePalette, y luego el SpriteTemplate
Por último, para destruirlo sería tan simple como:
Aclarar que si estamos usando la misma paleta para varios iconos, o sprites, no tenéis que crear la paleta para cada uno de ellos, con crearla una vez y usarla para todos, sobra, obviamente.
1.- Ahora buscaremos el archivo .c en el que queremos que se cargue nuestro querido sprite y lo abrimos, o en caso de que queramos que sea un nuevo archivo, pues lo creamos, aunque si no sabéis como crear nuevos archivos .c, no lo hagáis.
2.- Por aquí os voy a ir dejando todo el código que un sprite siempre va a necesitar para que se pueda cargar, y voy explicándolos uno a uno.
Código:
static const u16 nombrePaleta[] = INCBIN_U16("graphics/menu_icons/iconPal.gbapal");
static const u8 nombreSprite[] = INCBIN_U8("graphics/menu_icons/dex.4bpp");
Con estos códigos estamos guardando la paleta y el sprite respectivamente en unas variables, y es muy importante, que tan sólo cambiéis donde dice "nombrePaleta" y "nombreSprite" por el que queráis y la ruta donde se encuentran. Decir que se pueden crear nuevas carpetas en graphics si lo deseáis, en este caso, la carpeta es una que creé yo para el menú.
También es muy importante que carguéis primero las paletas y luego los sprites.
3.-
Código:
static EWRAM_DATA u8 iconNameEWRAM = 0;
4.-
Código:
static const struct OamData spriteNameOamData =
{
.y = 0, //Esto no hace lo que parece, no es necesario cambiarlo
.affineMode = 0, //Esto es el modo afín, lo usaremos para las animaciones de tipo afín, pero de momento, nos olvidamos y lo dejamos en 0
.objMode = 0, //Lo dejamos en 0
.mosaic = 0, //Lo dejamos en 0
.bpp = 0, //Lo dejamos en 0
.shape = 0, //Hace que el sprite sea un: cuadrado = 0, rectángulo horizontal = 1, rectángulo vertical = 2
.x = 0, //Esto no hace lo que parece, no es necesario cambiarlo
.matrixNum = 0, //Lo dejamos en 0
.size = 1, //Esto indica el tamaño de nuestro sprite, más abajo está la tabla
.tileNum = 0, //Lo dejamos en 0
.priority = 0, //Esto es la prioridad, a menor número, mayor prioridad, por tanto, para tener la máxima prioridad, lo dejamos en 0
.paletteNum = 0, //Esto no hace lo que parece, no es necesario cambiarlo
.affineParam = 0, //Esto lo dejaremos siempre en 0
};
Código:
8x8 = 0
16x16 = 1
32x32 = 2
64x64 = 3
Esta es la tabla de parámetros para la OAM que usaremos más adelante, id apuntando los nombres que le dais a cada cosa porque luego nos harán falta. Simplemente la editáis respecto a vuestras necesidades y listo.
He de decir, que si tenéis dos sprites con las mismas características, no creéis dos iguales, podéis usar el mismo para ambos (en este caso)
5.-
Código:
static const union AnimCmd nameSpriteAnimSeq0[] =
{
ANIMCMD_FRAME(0, 5),
ANIMCMD_END,
};
static const union AnimCmd *const nameSpriteAnimTable[] =
{
nameSpriteAnimSeq0,
};
Y ya tenemos todo lo que necesitábamos creando, por tanto, ahora tenemos que repetir este código con cada sprite que queramos cargar, y es totalmente obligatorio darle un nombre diferente a cada estructura.
Código:
struct SpriteSheet spriteSheet =
{
.data = nombreSprite,
.size = 512,
.tag = 12, //Este es lugar en que el sistema dibujará el sprite en la OAM
};
struct SpritePalette spritePalette =
{
.data = nombrePaleta,
.tag = 12, //Este es lugar en que el sistema dibujará el sprite en la OAM
};
struct SpriteTemplate spriteTemplate =
{
.tileTag = 12, //Este es lugar en que el sistema dibujará el sprite en la OAM
.paletteTag = 12, //Este es lugar en que el sistema dibujará el sprite en la OAM
.oam = &spriteNameOamData,
.anims = nameSpriteAnimTable,
.images = NULL, //Lo dejaremos siempre como NULL
.affineAnims = gDummySpriteAffineAnimTable, //Esto es para las animaciones afines, de nuevo, si no las usamos, dejaremos esto por defecto
.callback = SpriteCallbackDummy, //Esto es para las animaciones, si no las usaremos, también se quedará así
};
Como podéis comprobar, esta es la parte más importante, y donde se acumula todo aquello que hemos hecho con anterioridad.
Y como también podréis observar, os he señalado con negrita y colores los parámetros a los que debéis estar atentos, en este caso los colores naranjas corresponde a nombres que hemos declarado fuera o con anterioridad, y los azules son los que hemos declarado en el propio código. Sé que puede parecer algo exagerado ponerlo por colores, pero seguro que así lo veis más sencillo.
Debéis tener en cuenta que todos los parámetros que lleven "tag" como nombre, o como parte del nombre, no deben repetirse, me explico:
Por ejemplo, podemos crear la estructura de "SpriteSheet", "SpritePalette" y "SpriteTemplate" y usar en todas el número 12 como tag, pero teniendo en cuenta que estas estructuras van a corresponder al mismo Pokémon. Sin embargo, si creamos otras tres nuevas estructuras para otro icono, no debemos usar de nuevo el 12, si no cualquier otro número que no esté ocupado.
Y ahora, lo que todos estábamos esperando, cargar el sprite en pantalla, que lo haremos con esta serie de comandos:
Código:
LoadSpriteSheet(&spriteSheet);
LoadSpritePalette(&spritePalette);
iconNameEWRAM = CreateSprite(&spriteTemplate, x, y, 0);
Es muy importante hacerlo en este orden, pues primer cargamos el SpriteSheet, luego el SpritePalette, y luego el SpriteTemplate
Por último, para destruirlo sería tan simple como:
Código:
DestroySpriteAndFreeResources(&gSprites[iconNameEWRAM]);
Y eso es todo, cualquier duda la podéis dejar por los comentarios, decidme que os ha parecido el post y un +Gracias se agradece
¡Chau!
Última edición: