Sprites: variables y funciones para usar en GML
Los sprites en Game Maker Studio 2 es la parte visual de nuestro juego. Si no sabes exactamente de lo que hablo, mira este pequeña introducción a los sprites que hice en su momento, y es válida igualmente en la versión actual.
La principal diferencia es que ahora no tenemos un recurso de fondos o backgrounds, y tenemos uno nuevo llamado tilesets, pero al final tenemos que basarnos en los sprites para:
- crear animaciones para nuestros objetos.
- añadir fondos a nuestras rooms.
- crear y manipular tilesets.
- añadir sprites directamente a la room, como fondos animados.
La verdad es que a todo lo comentado, desde mi punto de vista, no le veo ninguna pega. Podemos decir que hay un criterio con sentido común.
Y después de decir mi opinión, vamos a lo que vamos. en su momento hablé del editor de sprites y del editor de imágenes de Game Maker Studio 2. YoYoGames intenta que se pueda hacer un juego sólo con su herramienta (al menos en pixel art), y te ofrece algunas opciones avanzadas para poder hacer animaciones, dibujar fondos, etc.
A la hora de programar también es posible manipular y gestionar los sprites (y las imágenes que contiene). Seguro que tienes muy claro que significa sprite_index
, pero, ¿sabrías usar la variable sprite_xoffset
?
Así que vamos a ver cada una de estas variables y funciones del sistema que nos ofrece Game Maker Studio 2, y un pequeño ejemplo de cómo usarlas para tus videojuegos.
Diferencia entre el recurso del sprite y el sprite del objeto
No sé si el título puede ser algo confuso, así que vamos a ver un ejemplo.
¿Qué diferencia hay entre la variable del objeto sprite_width
y la función sprite_get_width()
?
La variable sprite_width
se usa en un objeto, mejor dicho, se aplica a una instancia. Si el sprite de la instancia cambia por algún motivo, por ejemplo, le hacemo sun escalado para ampliar o reducir el sprite, el valor de sprite_width
también cambiará.
En cambio sprite_get_width()
se aplica al recurso del sprite. Es más, dentro de los paréntesis tienes que poner el sprite al que te refieres, por ejemplo sprite_get_width(spr_player)
. De esta manera, podemos saber el ancho del sprite, sin necesidad de tener un objeto con ese sprite, o preocuparnos si le ha pasado al sprite de esa instancia.
Supongo que la manera de distinguirlo de Game Maker Studio 2 es con una variable de instancia y con una función genérica. Así que si ya sabes que debes usar cuando quieres pensar en el recurso y que tienes usar cuando te refieres a la instancia.
Otro apunte más con sprite_width
: curiosamente esta variable es de solo lectura, es decir, si quieres modificar el ancho dle sprite debes hacerlo con image_xscale
. Un motivo más para escribir este artículo y así aclarar cuando debes usar cada cosa.
Obtener información del sprite
Vamos a ver las diferentes funciones que tenemos para obtener información de un sprite.
sprite_get_name
Esta función devuelve el nombre del sprite como un string o cadena. con este nombre podrías comprobar algunas cosas, pero no te servirá para referirte al sprite. Vamos a verlo con un ejemplo. Imagina el siguiente cógido
sprite_jugador = sprite_get_name(spr_player);
Ahora tenemos en la variable sprite el nombre del sprite, que no deja de ser “spr_player”. Si ahora queremos hacer esto:
sprite_index = sprite_jugador;
Nos va a dar un error. No podemos trabajar con sprites con textos.
TRUCO: si que podemos usar la función
asset_get_index ()
para poder usarlo como un sprite o cualquier recurso.
Esta función nos puede servir para jugar con parte del texto de los sprites. Por ejemplo, imagina que tienes un objeto jugador con diferentes armaduras(que peudes elegir). Lo más seguro es que tengas varios sprites como
spr_player_red_run spr_player_red_attack spr_player_red_death spr_player_blue_run spr_player_blue_attack spr_player_blue_death ...
Imagina que en algún momento necesitamos saber que color de armadura tiene, pero puede tener cualquiera de los tres sprites. Para no tener que hacer este if
:
if sprite_index == spr_player_blue_run or sprite_index == spr_player_blue_attack or spr_player_blue_death { ...//código }
o quizás mejor con un switch
switch (sprite_index) { case spr_player_blue_run: case spr_player_blue_attack: case spr_player_blue_death: //Código break; ... }
se puede hacer de una manera más sencilla
sprite_player = sprite_get_name(sprite_index); if string_pos( "blue",sprite_player) > 0 { //código }
El código es más sencillo, y además, si añades otro sprite por algún motivo, no tienes que acordarte ni modificar el código en esta parte.
sprite_get_number
La función sprite_get_number
nos dice el número de imágenes total del sprite. Recuerda que si un sprite tiene 5 imágenes, la imágenes se numeran con 0, 1, 2, 3 y 4.
Aunque pueda parecer curioso, y seguramente no lo uses nunca, es posible cambiar el número de imágenes de un sprite, ya sea creando un nuevo sprite o añadiendo nuevas imágenes mediante una función.
sprite_get_speed
Ahora en Game Maker Studio 2 puedes definir la velocidad en el mismo sprite, además de definirla en el juego, como siempre se ha hecho.
También es posible cambiarlo dentro de la misma instancia, con el sprite que tiene asociado, con la variable image_speed
.
Con sprite_get_speed
podríamos recuperar la velocidad inicial que le dijimos al sprite, sin necesidad de guardarlo previamente.
Recuerda que puedes definir la velocidad del sprite de dos maneras: Frames per second o Frames per game frame.
Otro ejemplo para ver las diferencias. Si usas Frames per second, y lo reduces a la mitad, estás pintando una imagen en el doble de tiempo (con números, si tú juego funciona a 30 fps, la mitad es una imagen cada 60 fps). Pero con Frames per game frame, lo que haces es pintar 30 veces la imagen en 60 fps.
¿Cuál de las dos es la que está configurada en el sprite? Mira la siguiente función.
sprite_get_speed_type
Con esta función sabremos si nuestro sprite tiene la velocidad configurada por Frames per second o por Frames per game frame.
Puede devolver una de estas dos constantes: spritespeed_framespersecond
o spritespeed_framepergameframe
.
sprite_get_width
Nos devuelve el ancho del sprite en píxeles. Recuerda que es su valor original, sin que se haya transformado en el objeto.
sprite_get_height
Nos devuelve la altura del sprite. Al igual que el anterior, es el valor de origen.
sprite_get_xoffset
¿Sabes cuando pones el valor de origen x/y en el sprite? Ese valor es el que usas para colocar el objeto que tiene ese sprite en la room, y siempre será la referencia.
Pero, ¿qué pasa si queremos saber cuál es la esquina izquierda de la imagen? ¿Cómo llegamos hasta ahí? Pues con sprite_get_xoffset
. Esta función nos devuelve el valor desplazado del sprite. Resumiendo, nos devuelve el valor x del origen del sprite.
sprite_get_yoffset
Lo mismo que todo lo anterior, pero para el valor y del origen del sprite.
Pongamos un ejemplo. Imagina que un objeto está centrado, es decir, el sprite tiene su origen en Middle Centre. Queremos que si llega al límite de la room siempre se vea toda la imagen. El código que pondría en el evento Other – Intersect boundary sería el siguiente:
if (x - sprite_get_xoffset (sprite_index) <0 ) { x = sprite_get_xoffset (sprite_index); } if (y - sprite_get_yoffset (sprite_index) <0 ) { y = sprite_get_yoffset (sprite_index); }
sprite_get_bbox_bottom
Supongo que ya sabes la diferencia entre el sprite y su máscara de colisión. Esta máscara puede tener un tamaño diferente del sprite, aunque lo habitual es usar una máscara rectangular que no implique mucho coste de proceso en las colisiones.
Para saber como está ubicada la máscara, nos imaginamos un rectángulo dentro del sprite. Ese rectángulo está definido con su posición left y top (izquierda y superior), y un tamaño que llega hasta el right y el bottom (derecha e inferior). Quedaría así:
Los límites los sabremos por cuatro funciones. Con sprite_get_bbox_bottom
sabemos el límite inferior, por tanto, si llamamos a esta función nos devolvería 86.
sprite_get_bbox_left
Nos dará la posición izquierda de la máscara. Si miramos la imagen anterior, sprite_get_bbox_left
nos dará 10.
sprite_get_bbox_right
Nos da la posición derecha del rectángulo de la máscara del sprite. Comparado con la imagen, sprite_get_bbox_right
nos dará 54.
sprite_get_bbox_top
Devolverá el límite superior de la máscara. sprite_get_bbox_left
nos dará 86 en el sprite de la imagen.
Resumen final
Hasta aquí hemos hablado de todas las funciones que nos da información de los sprites. Pero aún quedan muchas relacionadas con este recurso.
Tenemos funciones para manipular los sprites (añadir sprites nuevos, reemplazar alguno existente, guardarlos en una imagen aparte…), y sobretodo, funciones que nos da información al sprite asociado a un objeto (que son las más habituales).
Y si en vez de usar imágenes usamos animaciones de esqueleto con Spine, la manera de tratar los psrites no tienen nada que ver. Por ejemplo, en vez de cambiar de un sprite a otro, como puede ser de caminar a atacar, sería llamar a una animación distinta (sin cambiar de sprite).
Pero como llevo más de 1400 palabras, todo esto lo explico en una segunda parte ?.
Si quieres que hable siga hablando de estos temas dímelo. La intención es explicar casos prácticos de todas las funciones GML que necesites usar, así que cuando llegue el momento no tengas dudas de como hacer las cosas.
muy buen material me agrada.Tengo game maker 8.1 y necesitaría material para poderlo entender mejor si me puedes facilitar algunos buenos pdf o decir donde conseguir
Creo que la mayoría del GML podría servirte para la versión 8.1, al menos para programar la parte de objetos.
Hola, mi nombre es Alejandro vivo en Venezuela y tengo GM 8.1 y soy un novato en esto, de echo me acabo de descargar el programa y necesito algo de ayuda , podrías hacer un tutorial para hacer diálogos estilo pokemon.
ya sabes algo como que si el npc te ve cuando camines te detengas camine asía ti y empiece el dialogo.
Yo tengo este ejemplo de diálogos, espero que te sirva
https://www.aprendegamemaker.com/como-hacer-aventura-grafica-dialogos/