Tutoriales por Elias Orz. (YFGM)
¡Saludos! En este tutorial voy a explicar lo más básico de cómo usar la librería “Allegro” para el desarrollo de juegos en C++. Recuerdo que ya me habían pedido un tutorial sobre este tema (desde que subí mi juego de Pacman en C++) así que aquí lo posteo.
Existen dos versiones de la librería: la 4.4 y la más reciente 5.2. Aunque la versión 5 es la más nueva, en mi opinión cada una tiene sus propias ventajas y desventajas.
- Allegro 5 utiliza el GPU para acelerar los gráficos. Esto hace que las animaciones sean más fluidas, sobretodo en Windows, y además es compatible con iOS y Android.
- Allegro 4 solo utiliza el CPU (procesador) para dibujar los gráficos, lo cual lo hace compatible en casi todos los PC antiguos y modernos sin requerir de una GPU compatible. Con Allegro 4 también es posible hacer juegos para la plataforma DOS (MS-DOS), permitiendo correr los juegos en cualquier dispositivo donde exista un emulador de dicho sistema.
Antes de empezar, este tutorial asume que ya tienes un poco de conocimiento del lenguaje C o C++ en lo que respecta en el manejo de funciones, la declaración de variables y los punteros. Allegro no es un “motor” de juegos como Unity o GameMaker. Esta librería solo se encarga de la parte audiovisual y de los eventos. Tú eres libre de diseñar y estructurar el juego a tu preferencia.
Instalando lo necesario
Windows
Primero tenemos que descargar los archivos necesarios para utilizar Allegro y empezar con el código. En el enlace están los archivos necesarios para descargar:
Para el archivo "allegro-mingw-gcc-5.1" solo debes descargar el .zip o el .7z (a tu preferencia). El .7z es más ligero, pero no todos pueden abrirlo.
Cuando tengamos todo guardado, abrimos el instalador de CodeBlocks. No hace falta cambiar ninguna opción del instalador; solo presionamos Next (Siguiente) y dejamos que se instale...
Cuando haya terminado la instalación, extraemos el contenido del archivo de Allegro (allegro-mingw-gcc-5.1) a una carpeta nueva:
Tenemos que mover estas 3 carpetas al directorio donde se haya instalado MinGW. En nuestro caso, debe ser en una de estas ubicaciones:
Para Windows XP, la ruta es C:\Archivos de programa\CodeBlocks\MinGW
Para Windows 7, 8 y 10 de 32-bits, la ruta es C:\Program Files\CodeBlocks\MinGW
Para Windows 7, 8 y 10 de 64-bits, la ruta es C:\Program Files (x86)\CodeBlocks\MinGW
Con esto ya tenemos todo instalado para empezar a usar Allegro. Si descargamos las plantillas, podemos abrir uno de los proyectos (.cbp) con CodeBlocks y presionar F9 para correr el programa de prueba:
Si aparece esta ventana en Allegro 4, quiere decir que lo has hecho bien y puedes empezar a mirar los tutoriales más abajo
Si usaste la plantilla de Allegro 5, la ventana se cierra sola al cabo de 5 segundos, sin mostrar texto.
Si el programa da un error de compilación, asegúrate que hayas copiado los archivos a uno de los directorios que mencioné antes. Para mover los archivos a ese directorio vas a necesitar permisos de Administrador, pero solo debes presionar "Continuar" en el diálogo que te aparece antes de moverlos.
Link: Carpeta en Mediafire
Para el archivo "allegro-mingw-gcc-5.1" solo debes descargar el .zip o el .7z (a tu preferencia). El .7z es más ligero, pero no todos pueden abrirlo.
Cuando tengamos todo guardado, abrimos el instalador de CodeBlocks. No hace falta cambiar ninguna opción del instalador; solo presionamos Next (Siguiente) y dejamos que se instale...
Cuando haya terminado la instalación, extraemos el contenido del archivo de Allegro (allegro-mingw-gcc-5.1) a una carpeta nueva:
Tenemos que mover estas 3 carpetas al directorio donde se haya instalado MinGW. En nuestro caso, debe ser en una de estas ubicaciones:
Para Windows XP, la ruta es C:\Archivos de programa\CodeBlocks\MinGW
Para Windows 7, 8 y 10 de 32-bits, la ruta es C:\Program Files\CodeBlocks\MinGW
Para Windows 7, 8 y 10 de 64-bits, la ruta es C:\Program Files (x86)\CodeBlocks\MinGW
Con esto ya tenemos todo instalado para empezar a usar Allegro. Si descargamos las plantillas, podemos abrir uno de los proyectos (.cbp) con CodeBlocks y presionar F9 para correr el programa de prueba:
Si aparece esta ventana en Allegro 4, quiere decir que lo has hecho bien y puedes empezar a mirar los tutoriales más abajo
Si usaste la plantilla de Allegro 5, la ventana se cierra sola al cabo de 5 segundos, sin mostrar texto.
Si el programa da un error de compilación, asegúrate que hayas copiado los archivos a uno de los directorios que mencioné antes. Para mover los archivos a ese directorio vas a necesitar permisos de Administrador, pero solo debes presionar "Continuar" en el diálogo que te aparece antes de moverlos.
Linux
En distribuciones basadas en Debian (como Ubuntu, eOS y Mint) podemos usar el apt-get para instalar los paquetes necesarios:
Si queremos programar para Allegro 4.4, instalamos también el paquete liballegro4-dev:
O si queremos programar con Allegro 5, instalamos el paquete liballegro5-dev:
Cuando hayamos instalado todo, abrimos CodeBlocks y damos clic en "Create a new project". En la ventana seleccionamos "Console application" y en el asistente configuramos la carpeta donde queremos tener el proyecto y el lenguaje que usaremos (C o C++).
Cuando finalice el asistente, nos vamos al menú Project -> Build options, y en la pestaña "Linker settings" colocamos una de estas líneas en Other linker options:
Después abrimos la fuente “main.cpp” que se creó junto con el proyecto, y borramos todo el código para empezar los tutoriales de Allegro.
sudo apt-get install gcc g++ codeblocks pkg-config
Si queremos programar para Allegro 4.4, instalamos también el paquete liballegro4-dev:
sudo apt-get install liballegro4-dev
O si queremos programar con Allegro 5, instalamos el paquete liballegro5-dev:
sudo apt-get install liballegro5-dev
Cuando hayamos instalado todo, abrimos CodeBlocks y damos clic en "Create a new project". En la ventana seleccionamos "Console application" y en el asistente configuramos la carpeta donde queremos tener el proyecto y el lenguaje que usaremos (C o C++).
Cuando finalice el asistente, nos vamos al menú Project -> Build options, y en la pestaña "Linker settings" colocamos una de estas líneas en Other linker options:
`pkg-config --libs allegro`
si instalaste liballegro4-dev`pkg-config --libs allegro-5 allegro_image-5`
si instalaste liballegro5-devDespués abrimos la fuente “main.cpp” que se creó junto con el proyecto, y borramos todo el código para empezar los tutoriales de Allegro.
Tutoriales
Allegro 4
Lección 1: Primer programa
Lección 2: Cargando y dibujando sprites
Lección 3: Uso del teclado
Lección 4: Búfer doble (double-buffering)
Lección 5: Cuadros por segundo (FPS)
El código que por ahora vamos a tratar será el siguiente:
Si compilamos esta pequeña pieza de código y abrimos el programa, se creará una ventana de 640x480 y esperará a que el usuario presione una tecla para terminar la aplicación. Pero ahora veamos lo que hace cada línea.
Esta función (muy importante) es la que instala los componentes fundamentales de la biblioteca Allegro. Nunca hay que olvidar colocar esta función al principio de nuestra función main().
Esta función instala todas las rutinas del teclado, la cual también es muy importante. Básicamente con esta función podremos checar qué teclas están siendo presionadas, y poder hacer lo que queramos de acuerdo a ello.
Con esta función hacemos que nuestro juego tenga una profundidad de color de 32-bits (color verdadero) o con el valor que le demos. Puede ser 8 (para 256 colores), 16, 24 o 32. Si no ponemos esta función, la ventana se iniciaría con una profundidad de color de 8 (256 colores). Esta función siempre se debe colocar antes de set_gfx_mode!
Está función creará una ventana de 640x480 píxeles, con la profundidad de color que se mencionó anteriormente. En caso de que queramos arrancar el juego en pantalla completa, podemos usar GFX_AUTODETECT ó GFX_AUTODETECT_FULLSCREEN. Esta función retornará un valor mayor a 0 si no se pudo iniciar el modo gráfico.
Con esta función hacemos que nuestro juego se pause hasta que una tecla sea presionada, puede ser cualquier tecla.
Todos los programas diseñados con Allegro deben tener esta función, al final de la última llave de la función main(). En otro caso, nos dará un error.
Y aquí concluye la primera lección. Ya sabemos cómo instalar la librería e iniciar el modo gráfico. Esto es muy importante en todos los programas que utilicen Allegro.
Nunca olvides incluir la librería <allegro.h> al principio de tu código, si no, nada va a funcionar!
PHP:
// main.cpp
// Tutorial de programación de juegos con C++ y Allegro
#include <allegro.h>
int main()
{
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
readkey();
return 0;
}
END_OF_MAIN()
Si compilamos esta pequeña pieza de código y abrimos el programa, se creará una ventana de 640x480 y esperará a que el usuario presione una tecla para terminar la aplicación. Pero ahora veamos lo que hace cada línea.
PHP:
allegro_init();
Esta función (muy importante) es la que instala los componentes fundamentales de la biblioteca Allegro. Nunca hay que olvidar colocar esta función al principio de nuestra función main().
PHP:
install_keyboard();
Esta función instala todas las rutinas del teclado, la cual también es muy importante. Básicamente con esta función podremos checar qué teclas están siendo presionadas, y poder hacer lo que queramos de acuerdo a ello.
PHP:
set_color_depth(32);
Con esta función hacemos que nuestro juego tenga una profundidad de color de 32-bits (color verdadero) o con el valor que le demos. Puede ser 8 (para 256 colores), 16, 24 o 32. Si no ponemos esta función, la ventana se iniciaría con una profundidad de color de 8 (256 colores). Esta función siempre se debe colocar antes de set_gfx_mode!
PHP:
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
Está función creará una ventana de 640x480 píxeles, con la profundidad de color que se mencionó anteriormente. En caso de que queramos arrancar el juego en pantalla completa, podemos usar GFX_AUTODETECT ó GFX_AUTODETECT_FULLSCREEN. Esta función retornará un valor mayor a 0 si no se pudo iniciar el modo gráfico.
PHP:
readkey();
Con esta función hacemos que nuestro juego se pause hasta que una tecla sea presionada, puede ser cualquier tecla.
PHP:
END_OF_MAIN()
Todos los programas diseñados con Allegro deben tener esta función, al final de la última llave de la función main(). En otro caso, nos dará un error.
Y aquí concluye la primera lección. Ya sabemos cómo instalar la librería e iniciar el modo gráfico. Esto es muy importante en todos los programas que utilicen Allegro.
Nunca olvides incluir la librería <allegro.h> al principio de tu código, si no, nada va a funcionar!
Lección 2: Cargando y dibujando sprites
En este paso vamos a aprender cómo cargar imágenes (o sprites) desde ficheros externos como BMP o PCX. También vamos a aprender cómo dibujarlas en pantalla, y así darle un mejor aspecto a nuestro juego.
Las imágenes en Allegro siempre se deben definir de tipo BITMAP.
Es decir, cuando queramos añadir una imagen primero debemos declarar una variable de tipo BITMAP:
Como los BITMAP son punteros, debemos colocar un ( * ) antes de la variable que declaremos.
Puedes declarar estas variables antes de la función
Ahora, para cargar una imagen que tengamos en el ordenador, debemos hacerlo con la función
El primer argumento es el nombre de la imagen que queremos cargar en la variable "mi_sprite". Puede ser una imagen BMP, TGA, LBM o PCX.
El segundo argumento es una variable donde almacenaremos la paleta de colores de nuestra imagen, en caso de que sea de 256 colores (8-bits). Pero como no vamos a usar este argumento, solo ponemos NULL. Todas las funciones de
Ya que hayamos cargado nuestra imagen, podemos dibujarla en pantalla con la función
De esta forma se dibujará la imagen
El primer argumento es el BITMAP donde queremos dibujar nuestro sprite. Debemos poner
El segundo argumento es el sprite que vamos a dibujar. Debe ser un BITMAP que ya hayamos cargado, de otra forma, nos dará un error.
El tercero y cuarto argumento son las coordenadas x,y donde queremos dibujar nuestro sprite.
Por último nuestro código ha quedado de la siguiente manera:
Como mencioné en la lección anterior, el programa esperará a que el usuario presione cualquier tecla, pero antes se podrá ver nuestro sprite en la posición 0,0 de la pantalla.
Las imágenes en Allegro siempre se deben definir de tipo BITMAP.
Es decir, cuando queramos añadir una imagen primero debemos declarar una variable de tipo BITMAP:
PHP:
BITMAP *mi_sprite;
Como los BITMAP son punteros, debemos colocar un ( * ) antes de la variable que declaremos.
Puedes declarar estas variables antes de la función
main()
(para que sean globales), o justo después del set_gfx_mode
.Ahora, para cargar una imagen que tengamos en el ordenador, debemos hacerlo con la función
load_bitmap
, como se muestra en la línea:
PHP:
mi_sprite = load_bitmap("imagen.bmp", NULL);
El primer argumento es el nombre de la imagen que queremos cargar en la variable "mi_sprite". Puede ser una imagen BMP, TGA, LBM o PCX.
El segundo argumento es una variable donde almacenaremos la paleta de colores de nuestra imagen, en caso de que sea de 256 colores (8-bits). Pero como no vamos a usar este argumento, solo ponemos NULL. Todas las funciones de
load_bitmap
deben colocarse después de set_gfx_mode
.Ya que hayamos cargado nuestra imagen, podemos dibujarla en pantalla con la función
draw_sprite
:
PHP:
draw_sprite(screen, mi_sprite, 0, 0);
De esta forma se dibujará la imagen
mi_sprite
en la posición 0,0 de la pantalla.El primer argumento es el BITMAP donde queremos dibujar nuestro sprite. Debemos poner
screen
si queremos dibujarlo en la pantalla del juego.El segundo argumento es el sprite que vamos a dibujar. Debe ser un BITMAP que ya hayamos cargado, de otra forma, nos dará un error.
El tercero y cuarto argumento son las coordenadas x,y donde queremos dibujar nuestro sprite.
Por último nuestro código ha quedado de la siguiente manera:
PHP:
#include <allegro.h>
BITMAP *mi_sprite;
int main()
{
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
mi_sprite = load_bitmap("imagen.bmp", NULL);
draw_sprite(screen, mi_sprite, 0, 0);
readkey();
return 0;
}
END_OF_MAIN()
Como mencioné en la lección anterior, el programa esperará a que el usuario presione cualquier tecla, pero antes se podrá ver nuestro sprite en la posición 0,0 de la pantalla.
Lección 3: Uso del teclado
En este paso vamos a saber a manipular las funciones del teclado. Por ahora, solo vamos a ver cómo realizar ciertas acciones al momento de que alguna tecla esté presionada. También vamos a hacer que nuestro juego no se pare hasta que el usuario presione la tecla de Escape (ESC), creando un "ciclo" o loop del juego.
Como ya no vamos a usar la función de readkey, podemos suprimirla de nuestro código.
Primero vamos a comenzar usando la condición while, que servirá para que el juego siga ejecutándose hasta que cierta condición se cumpla.
En el codigo anterior se puede ver que he puesto la función draw_sprite adentro de la condición while, de tal forma que el sprite siga dibujándose en la pantalla mientras la tecla ESC no sea presionada. Si esta tecla es presionada, el juego terminaría de inmediato.
La variable pre-definida llamada key, es la que nos sirve para checar las teclas que están presionadas.
De esta forma es como se debe usar la variable key. Por ejemplo, para checar otros botones podemos utilizar la condición if, como se muestra:
Estos deben ir (obviamente) adentro de la condición while, a no ser que quieras usarlos en otra parte del código.
Entonces, vamos a hacer que nuestro sprite se mueva cuando presionemos alguna de las teclas de dirección. Para eso vamos a crear dos variables, al principio de nuestro código:
Estas dos variables las usaremos para indicar la posición actual de nuestro sprite, y cambiarán al momento de presionar las teclas de dirección. Adentro de nuestra condición while, pondremos:
Ahora solo nos toca cambiar algunos de los argumentos de la función draw_sprite. Los dos últimos los reemplazaremos por player_x y player_y respectivamente:
De esta forma nuestro sprite cambiará su posición cuando presionemos alguna de las teclas de dirección.
Ya para finalizar, si probamos el juego hasta aquí, notaremos que corre a una velocidad demasiado rápida, y que tal vez esté ocupado el 100% de nuestro CPU. Para evitar esto, debemos añadir un rest(1); al final de la condición while.
Ahora, el código ya completado:
Y de esta forma concluye la Lección 3.
Como ya no vamos a usar la función de readkey, podemos suprimirla de nuestro código.
Primero vamos a comenzar usando la condición while, que servirá para que el juego siga ejecutándose hasta que cierta condición se cumpla.
PHP:
while (!key[KEY_ESC])
{
draw_sprite(screen, mi_sprite, 0, 0);
}
En el codigo anterior se puede ver que he puesto la función draw_sprite adentro de la condición while, de tal forma que el sprite siga dibujándose en la pantalla mientras la tecla ESC no sea presionada. Si esta tecla es presionada, el juego terminaría de inmediato.
La variable pre-definida llamada key, es la que nos sirve para checar las teclas que están presionadas.
De esta forma es como se debe usar la variable key. Por ejemplo, para checar otros botones podemos utilizar la condición if, como se muestra:
PHP:
if (key[KEY_LEFT])
...
if (key[KEY_RIGHT])
...
if (key[KEY_X])
...
Estos deben ir (obviamente) adentro de la condición while, a no ser que quieras usarlos en otra parte del código.
Entonces, vamos a hacer que nuestro sprite se mueva cuando presionemos alguna de las teclas de dirección. Para eso vamos a crear dos variables, al principio de nuestro código:
PHP:
int player_x = 0;
int player_y = 0;
Estas dos variables las usaremos para indicar la posición actual de nuestro sprite, y cambiarán al momento de presionar las teclas de dirección. Adentro de nuestra condición while, pondremos:
PHP:
if (key[KEY_LEFT])
player_x--;
if (key[KEY_RIGHT])
player_x++;
if (key[KEY_UP])
player_y--;
if (key[KEY_DOWN])
player_y++;
Ahora solo nos toca cambiar algunos de los argumentos de la función draw_sprite. Los dos últimos los reemplazaremos por player_x y player_y respectivamente:
PHP:
draw_sprite(screen, mi_sprite, player_x, player_y);
De esta forma nuestro sprite cambiará su posición cuando presionemos alguna de las teclas de dirección.
Ya para finalizar, si probamos el juego hasta aquí, notaremos que corre a una velocidad demasiado rápida, y que tal vez esté ocupado el 100% de nuestro CPU. Para evitar esto, debemos añadir un rest(1); al final de la condición while.
Ahora, el código ya completado:
PHP:
#include <allegro.h>
BITMAP *mi_sprite;
int player_x = 0;
int player_y = 0;
int main()
{
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
mi_sprite = load_bitmap("imagen.bmp", NULL);
while (!key[KEY_ESC])
{
if (key[KEY_LEFT])
player_x--;
if (key[KEY_RIGHT])
player_x++;
if (key[KEY_UP])
player_y--;
if (key[KEY_DOWN])
player_y++;
draw_sprite(screen, mi_sprite, player_x, player_y);
rest(1);
}
return 0;
}
END_OF_MAIN()
Y de esta forma concluye la Lección 3.
Lección 4: Búfer doble (double-buffering)
Seguramente ya habrás escuchado este término en algunos juegos o emuladores. Esta técnica sirve para evitar que los sprites dejen rastro al moverse por la pantalla. También sirve para reducir los "parpadeos" que ocurren en la pantalla del juego, y así tener una mejor experiencia.
Primero vamos a declarar una nueva variable de tipo BITMAP. Este BITMAP lo usaremos para dibujar todo lo de nuestro juego, y después copiaremos el contenido de ese BITMAP a la pantalla del juego (screen). De esta forma crearemos lo que se le llama double-buffering para reducir los parpadeos en el juego:
Después, de preferencia que esté después de la función set_gfx_mode, alojamos la memoria suficiente para el BITMAP buffer:
SCREEN_W y SCREEN_H son variables que se definen automaticamente tras usar la función de set_gfx_mode. Éstas toman los valores del tamaño del ancho de la pantalla, y el alto respectivamente.
Para empezar a dibujar todo a nuestro buffer, primero debemos limpiar el contenido de éste con la función clear_bitmap y como argumento buffer. Esta función es muy importante ya que si no la colocamos en nuestro loop, la imagen no se refrescará adecuadamente y todo lo que hagamos en el juego dejará rastro. Así que por eso la pondremos antes de las funciones que dibujaban a la pantalla del juego, como draw_sprite
Después de esto, tenemos que cambiar el primer argumento de draw_sprite por buffer. Así le estaremos indicando que queremos dibujar nuestro sprite al buffer y no directamente a la pantalla del juego.
draw_sprite(buffer, mi_sprite, player_x, player_y);
Y por último, usaremos la función blit después de las funciones que dibujan al buffer. De este modo hacemos que el contenido de buffer se copie a la pantalla del juego (screen):
La función blit sirve para copiar el contenido de un BITMAP a otro BITMAP especificando la posición de origen X,Y y la posición de destino X,Y. También especificamos el tamaño, en los últimos dos argumentos.
Y de esta forma habremos terminado de hacer el búfer doble. Aquí el código final:
Recuerden que debemos dibujar todo al buffer y no al screen. Si dibujamos todo en screen causará que el juego parpadee constantemente, y el double-buffering no habrá servido de nada.
Primero vamos a declarar una nueva variable de tipo BITMAP. Este BITMAP lo usaremos para dibujar todo lo de nuestro juego, y después copiaremos el contenido de ese BITMAP a la pantalla del juego (screen). De esta forma crearemos lo que se le llama double-buffering para reducir los parpadeos en el juego:
PHP:
BITMAP *buffer;
Después, de preferencia que esté después de la función set_gfx_mode, alojamos la memoria suficiente para el BITMAP buffer:
PHP:
buffer = create_bitmap(SCREEN_W, SCREEN_H);
SCREEN_W y SCREEN_H son variables que se definen automaticamente tras usar la función de set_gfx_mode. Éstas toman los valores del tamaño del ancho de la pantalla, y el alto respectivamente.
Para empezar a dibujar todo a nuestro buffer, primero debemos limpiar el contenido de éste con la función clear_bitmap y como argumento buffer. Esta función es muy importante ya que si no la colocamos en nuestro loop, la imagen no se refrescará adecuadamente y todo lo que hagamos en el juego dejará rastro. Así que por eso la pondremos antes de las funciones que dibujaban a la pantalla del juego, como draw_sprite
PHP:
clear_bitmap(buffer);
Después de esto, tenemos que cambiar el primer argumento de draw_sprite por buffer. Así le estaremos indicando que queremos dibujar nuestro sprite al buffer y no directamente a la pantalla del juego.
draw_sprite(buffer, mi_sprite, player_x, player_y);
Y por último, usaremos la función blit después de las funciones que dibujan al buffer. De este modo hacemos que el contenido de buffer se copie a la pantalla del juego (screen):
PHP:
blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
La función blit sirve para copiar el contenido de un BITMAP a otro BITMAP especificando la posición de origen X,Y y la posición de destino X,Y. También especificamos el tamaño, en los últimos dos argumentos.
Y de esta forma habremos terminado de hacer el búfer doble. Aquí el código final:
PHP:
#include <allegro.h>
BITMAP *buffer;
BITMAP *mi_sprite;
int player_x = 0;
int player_y = 0;
int main()
{
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
buffer = create_bitmap(SCREEN_W, SCREEN_H);
mi_sprite = load_bitmap("imagen.bmp", NULL);
while (!key[KEY_ESC])
{
if (key[KEY_LEFT])
player_x--;
if (key[KEY_RIGHT])
player_x++;
if (key[KEY_UP])
player_y--;
if (key[KEY_DOWN])
player_y++;
clear_bitmap(buffer);
draw_sprite(buffer, mi_sprite, player_x, player_y);
blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
rest(1);
}
return 0;
}
END_OF_MAIN()
Recuerden que debemos dibujar todo al buffer y no al screen. Si dibujamos todo en screen causará que el juego parpadee constantemente, y el double-buffering no habrá servido de nada.
Lección 5: Cuadros por segundo (FPS)
Tal vez hayas notado que tu juego no siempre corre con la misma velocidad, o al pasarlo a otro equipo notaste que la velocidad era más lenta o más rápida. Pues bien, en este paso aprenderemos cómo hacer que nuestro juego siempre corra a una velocidad constante, en cuadros por segundo (FPS). También aprenderemos a usar los Timers, que son algo muy importante cuando se desea hacer algo tras pasar cierta cantidad de tiempo, en segundos o milisegundos.
Primero tenemos que declarar una variable necesaria para controlar los FPS del juego. A ésta la llamaremos speed_counter y la pondremos (de preferencia) antes de las otras variables declaradas:
Esta variable la tenemos que declarar como volatile y le almacenaremos el valor 0.
Después tenemos que declarar una procedura cuya función será incrementar 1 unidad a la variable speed_counter cada vez que la llamemos. La definimos como sigue:
Esta función o procedura la tenemos que llamar cada vez que pase un frame en nuestro juego. Por ejemplo, si queremos que nuestro juego corra a 30 FPS, esta función la tenemos que llamar 30 veces por segundo, y para esto, seguiremos con el sig. paso.
Justo antes del bucle while, debemos poner estas funciones especiales llamadas LOCK_VARIABLE y LOCK_FUNCTION, y como argumentos tenemos que poner nuestra variable y nuestra función respectivamente:
Y para iniciar nuestro Timer que controlará el FPS del juego, usamos la función install_int_ex como sigue:
De esta forma nuestra procedura llamada inc_speed_counter se ejecutará de forma automática 30 veces por segundo (o el número que tú le des, depende de cuántos FPS quieres que corra el juego) y por lo tanto, el valor de speed_counter también se incrementará 1 unidad cada vez que la función se ejecute. Así podremos realizar las acciones que queramos mientras el valor de speed_counter sea mayor a 0.
Por último, para hacer que nuestro juego se actualice cada vez que el valor de speed_counter sea mayor a 0, re-organizaremos todo lo que se encuentra adentro del bucle while como sigue:[/FONT]
Así le estaremos indicando al juego que solo se actualice cada vez que la variable speed_counter sea mayor a 0. Si es así, volvemos a ponerlo en 0 para que la próxima vez que la variable speed_counter tenga un valor de 1 se vuelva a actualizar el juego, y así sucesivamente.
Y aquí el código final de nuestro juego de prueba:
Así nuestro juego siempre correrá a la misma velocidad independientemente de que se traslade a otro equipo.
Primero tenemos que declarar una variable necesaria para controlar los FPS del juego. A ésta la llamaremos speed_counter y la pondremos (de preferencia) antes de las otras variables declaradas:
PHP:
volatile int speed_counter = 0;
Esta variable la tenemos que declarar como volatile y le almacenaremos el valor 0.
Después tenemos que declarar una procedura cuya función será incrementar 1 unidad a la variable speed_counter cada vez que la llamemos. La definimos como sigue:
PHP:
void inc_speed_counter()
{
speed_counter++;
}
END_OF_FUNCTION(inc_speed_conuter)
Esta función o procedura la tenemos que llamar cada vez que pase un frame en nuestro juego. Por ejemplo, si queremos que nuestro juego corra a 30 FPS, esta función la tenemos que llamar 30 veces por segundo, y para esto, seguiremos con el sig. paso.
Justo antes del bucle while, debemos poner estas funciones especiales llamadas LOCK_VARIABLE y LOCK_FUNCTION, y como argumentos tenemos que poner nuestra variable y nuestra función respectivamente:
PHP:
LOCK_VARIABLE(speed_counter);
LOCK_FUNCTION(inc_speed_counter);
Y para iniciar nuestro Timer que controlará el FPS del juego, usamos la función install_int_ex como sigue:
PHP:
install_int_ex(inc_speed_counter, BPS_TO_TIMER(30));
De esta forma nuestra procedura llamada inc_speed_counter se ejecutará de forma automática 30 veces por segundo (o el número que tú le des, depende de cuántos FPS quieres que corra el juego) y por lo tanto, el valor de speed_counter también se incrementará 1 unidad cada vez que la función se ejecute. Así podremos realizar las acciones que queramos mientras el valor de speed_counter sea mayor a 0.
Por último, para hacer que nuestro juego se actualice cada vez que el valor de speed_counter sea mayor a 0, re-organizaremos todo lo que se encuentra adentro del bucle while como sigue:[/FONT]
PHP:
while (!key[KEY_ESC])
{
if (speed_counter > 0)
{
speed_counter = 0;
if (key[KEY_LEFT])
player_x--;
if (key[KEY_RIGHT])
player_x++;
if (key[KEY_UP])
player_y--;
if (key[KEY_DOWN])
player_y++;
clear_bitmap(buffer);
draw_sprite(buffer, mi_sprite, player_x, player_y);
blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
}
rest(1);
}
Así le estaremos indicando al juego que solo se actualice cada vez que la variable speed_counter sea mayor a 0. Si es así, volvemos a ponerlo en 0 para que la próxima vez que la variable speed_counter tenga un valor de 1 se vuelva a actualizar el juego, y así sucesivamente.
Y aquí el código final de nuestro juego de prueba:
PHP:
#include <allegro.h>
volatile int speed_counter = 0;
void inc_speed_counter()
{
speed_counter++;
}
END_OF_FUNCTION(inc_speed_conuter)
BITMAP *buffer;
BITMAP *mi_sprite;
int player_x = 0;
int player_y = 0;
int main()
{
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
buffer = create_bitmap(SCREEN_W, SCREEN_H);
mi_sprite = load_bitmap("imagen.bmp", NULL);
LOCK_VARIABLE(speed_counter);
LOCK_FUNCTION(inc_speed_counter);
install_int_ex(inc_speed_counter, BPS_TO_TIMER(30));
while (!key[KEY_ESC])
{
if (speed_counter > 0)
{
speed_counter--;
if (key[KEY_LEFT])
player_x--;
if (key[KEY_RIGHT])
player_x++;
if (key[KEY_UP])
player_y--;
if (key[KEY_DOWN])
player_y++;
clear_bitmap(buffer);
draw_sprite(buffer, mi_sprite, player_x, player_y);
blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
}
rest(1);
}
return 0;
}
END_OF_MAIN()
Así nuestro juego siempre correrá a la misma velocidad independientemente de que se traslade a otro equipo.
Allegro 5
Lección 1: Primer programa
Lección 2: Eventos
Lección 3: Sprites y FPS
Lección 4: Uso del teclado
El código que vamos a tratar será el siguiente:
Si compilamos esta pequeña pieza de código y lo ejecutamos, veremos que se crea una nueva ventana (de 640x480) que tras pasar 5 segundos se cerrará. Pero ahora veamos lo que hace el código...
Estas son las librerías que normalmente usaríamos en nuestro juego. Aunque en el código no se usa ninguna función de stdio.h de todas formas la incluí para futuras ocasiones.
Aquí declaramos una variable de tipo ALLEGRO_DISPLAY, que es la que se encargará de mostrar la ventana de nuestro juego.
Esta función se encarga de iniciar los componentes básicos para utilizar Allegro. Nunca debemos olvidar ponerla al principio de la función main()! Esta función retornará un valor de cero si ha fallado.
Con la función "al_create_display" creamos una ventana para nuestro juego con las dimensiones dadas, en ancho y en alto.
Con esta función hacemos que la pantalla del juego se "borre" y se reestablezca de color negro (o con los valores RGB que tú le des).
Esta función hace que todos los cambios que hemos hecho a la pantalla del juego se visualizen. Es como "refrescar" la pantalla para volver a dibujar en ella.
La función "al_rest" hace que el juego se pause por el tiempo dado, en segundos. En este caso, 5 segundos.
Con esta función hacemos que la ventana o la pantalla de nuestro juego se "destruya", liberando la memoria.
Siempre que queramos terminar el juego, debemos liberar la memoria de todas las variables en Allegro que hayamos creado, justo como nuestro "display".
En caso de que nuestro juego se haya ejecutado satisfactoriamente, siempre retornamos 0.
Y aquí termina la primera lección para Allegro 5.
PHP:
// main.cpp
// Tutorial de programación de juegos en C++ y Allegro 5
#include <stdio.h>
#include <allegro5/allegro.h>
ALLEGRO_DISPLAY *display;
int main()
{
al_init();
display = al_create_display(640, 480);
al_clear_to_color(al_map_rgb(0, 0, 0));
al_flip_display();
al_rest(5.0);
al_destroy_display(display);
return 0;
}
Si compilamos esta pequeña pieza de código y lo ejecutamos, veremos que se crea una nueva ventana (de 640x480) que tras pasar 5 segundos se cerrará. Pero ahora veamos lo que hace el código...
PHP:
#include <stdio.h>
#include <allegro5/allegro.h>
Estas son las librerías que normalmente usaríamos en nuestro juego. Aunque en el código no se usa ninguna función de stdio.h de todas formas la incluí para futuras ocasiones.
PHP:
ALLEGRO_DISPLAY *display
Aquí declaramos una variable de tipo ALLEGRO_DISPLAY, que es la que se encargará de mostrar la ventana de nuestro juego.
PHP:
al_init();
Esta función se encarga de iniciar los componentes básicos para utilizar Allegro. Nunca debemos olvidar ponerla al principio de la función main()! Esta función retornará un valor de cero si ha fallado.
PHP:
display = al_create_display(640, 480);
Con la función "al_create_display" creamos una ventana para nuestro juego con las dimensiones dadas, en ancho y en alto.
PHP:
al_clear_to_color(al_map_rgb(0, 0, 0));
Con esta función hacemos que la pantalla del juego se "borre" y se reestablezca de color negro (o con los valores RGB que tú le des).
PHP:
al_flip_display();
Esta función hace que todos los cambios que hemos hecho a la pantalla del juego se visualizen. Es como "refrescar" la pantalla para volver a dibujar en ella.
PHP:
al_rest(5.0);
La función "al_rest" hace que el juego se pause por el tiempo dado, en segundos. En este caso, 5 segundos.
PHP:
al_destroy_display(display);
Con esta función hacemos que la ventana o la pantalla de nuestro juego se "destruya", liberando la memoria.
Siempre que queramos terminar el juego, debemos liberar la memoria de todas las variables en Allegro que hayamos creado, justo como nuestro "display".
PHP:
return 0;
En caso de que nuestro juego se haya ejecutado satisfactoriamente, siempre retornamos 0.
Y aquí termina la primera lección para Allegro 5.
Lección 2: Eventos
En esta lección veremos cómo utilizar los eventos en Allegro, introducidos en la versión 5.0.
A partir de esta lección vamos a usar el bucle "while" para mantener nuestro juego en ejecución.
El código que vamos a tratar será el siguiente:
El codigo se basa del tutorial anterior, así que solamente explicaré los añadidos y los cambios
Aquí creamos una variable del tipo ALLEGRO_EVENT_QUEUE que se usará para registrar los objetos de donde queremos recibir los eventos.
Se asigna la memoria suficiente al objeto event_queue, que como mencioné antes, es en donde registramos todos los eventos de nuestro juego.
Para recibir eventos de nuestro display tenemos que registrarla al "event_queue" por medio de la función "al_register_event_source".
La función "al_get_display_event_source" toma un argumento, el cual debe ser un objeto del tipo ALLEGRO_DISPLAY de donde queremos recibir los eventos, en nuestro caso, display.
Para estar informados de cualquier evento que pueda ocurrir en nuestro juego, tenemos que crear una variable del tipo ALLEGRO_EVENT, que es donde recibimos todos los eventos que pasen en nuestro juego.
Con esta función hacemos que el juego se espere hasta recibir un evento de los que tenemos registrados. Como solamente registramos nuestro display, solo podemos recibir eventos de este objeto.
Primero, checamos si el evento que recibimos fue del tipo ALLEGRO_EVENT_DISPLAY_CLOSE, o sea, cuando el botón "X" para cerrar la ventana es presionado. Si es correcto, el bucle "while" se romperá por medio del comando "break", y por lo tanto, el juego terminará.
De la misma forma como lo hicimos con el display, tenemos que destruir el objeto "event_queue" para liberar la memoria asignada.
A partir de esta lección vamos a usar el bucle "while" para mantener nuestro juego en ejecución.
El código que vamos a tratar será el siguiente:
PHP:
// main.cpp
// Tutorial de programación de juegos en C++ y Allegro 5
#include <stdio.h>
#include <allegro5/allegro.h>
ALLEGRO_DISPLAY *display;
ALLEGRO_EVENT_QUEUE *event_queue;
int main()
{
al_init();
display = al_create_display(640, 480);
event_queue = al_create_event_queue();
al_register_event_source(event_queue, al_get_display_event_source(display));
al_clear_to_color(al_map_rgb(0, 0, 0));
al_flip_display();
while (1)
{
ALLEGRO_EVENT event;
al_wait_for_event(event_queue, &event);
if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
break;
al_clear_to_color(al_map_rgb(0, 0, 0));
al_flip_display();
}
al_destroy_display(display);
al_destroy_event_queue(event_queue);
return 0;
}
El codigo se basa del tutorial anterior, así que solamente explicaré los añadidos y los cambios
PHP:
ALLEGRO_EVENT_QUEUE *event_queue;
Aquí creamos una variable del tipo ALLEGRO_EVENT_QUEUE que se usará para registrar los objetos de donde queremos recibir los eventos.
PHP:
event_queue = al_create_event_queue();
Se asigna la memoria suficiente al objeto event_queue, que como mencioné antes, es en donde registramos todos los eventos de nuestro juego.
PHP:
al_register_event_source(event_queue, al_get_display_event_source(display));
Para recibir eventos de nuestro display tenemos que registrarla al "event_queue" por medio de la función "al_register_event_source".
La función "al_get_display_event_source" toma un argumento, el cual debe ser un objeto del tipo ALLEGRO_DISPLAY de donde queremos recibir los eventos, en nuestro caso, display.
PHP:
ALLEGRO_EVENT event;
Para estar informados de cualquier evento que pueda ocurrir en nuestro juego, tenemos que crear una variable del tipo ALLEGRO_EVENT, que es donde recibimos todos los eventos que pasen en nuestro juego.
PHP:
al_wait_for_event(event_queue, &event);
Con esta función hacemos que el juego se espere hasta recibir un evento de los que tenemos registrados. Como solamente registramos nuestro display, solo podemos recibir eventos de este objeto.
PHP:
if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
break;
Primero, checamos si el evento que recibimos fue del tipo ALLEGRO_EVENT_DISPLAY_CLOSE, o sea, cuando el botón "X" para cerrar la ventana es presionado. Si es correcto, el bucle "while" se romperá por medio del comando "break", y por lo tanto, el juego terminará.
PHP:
al_destroy_event_queue(event_queue);
De la misma forma como lo hicimos con el display, tenemos que destruir el objeto "event_queue" para liberar la memoria asignada.
Lección 3: Sprites y FPS
En esta lección aprenderemos cómo cargar y dibujar imágenes o sprites en la pantalla del juego. También aprenderemos cómo limitar el FPS de nuestro juego con el uso de los timers.
El código que vamos a tratar será el siguiente:
En esta lección comenzaremos a usar las variables del tipo ALLEGRO_BITMAP, que son como si fueran los equivalentes a los BITMAP de Allegro 4.4.
Para usar imágenes en nuestro juego, debemos incluir la librería "allegro_image.h" que servirá para tener a disposición todas las funciones para manipular y dibujar las imagenes o sprites.
Esta variable del tipo ALLEGRO_TIMER será la que se encargará de avisarnos en qué momento debemos actualizar el juego.
Para incluir una imagen o sprite a nuestro juego, debemos declarar una nueva variable del tipo ALLEGRO_BITMAP como un puntero.
Declaramos una nueva variable del tipo int que nos servirá para saber en qué momento tenemos que actualizar la pantalla del juego (mientras tenga un valor de 1).
Es muy importante colocar esta función después de "al_init();" si es que queremos usar imágenes en nuestro juego.
Aquí creamos el timer que limitará el FPS de nuestro juego. La función "al_create_timer" toma un argumento, que es cada cuándo se va a recibir un evento de este timer (en segundos), en nuestro caso ponemos 1.0 / 60 si queremos que el juego corra a 60 cuadros por segundo.
Con esta función (al_load_bitmap) podemos cargar una imagen desde nuestra PC. Puede ser en casi cualquier formato, incluyendo PNG, BMP o TGA.
Para que podamos recibir eventos de nuestro timer, tenemos que registrarlo por medio de las funciones "al_register_event_source" y "al_get_timer_event_source" respectivamente.
Con esta función iniciamos el timer que limitará el FPS del juego. En nuestro caso le hemos puesto que se ejecute 60 veces por segundo...
Primero, checamos si el evento que recibimos viene de nuestro timer. Si es así, cambiamos el valor de la variable "redraw" a 1.
Si el valor de la variable "redraw" es mayor a 0, hacemos que la imagen almacenada en mi_sprite se dibuje en pantalla por medio de la función "al_draw_bitmap". Ésta toma 4 argumentos:
El primer argumento toma un objeto del tipo ALLEGRO_BITMAP, en este caso, mi_sprite.
Los siguientes dos argumentos son las coordenadas x,y donde queremos dibujar el sprite.
Y con el último argumento especificamos si queremos dibujar el sprite volteado horizontal o verticalmente. Puede ser una de las dos:
ALLEGRO_FLIP_HORIZONTAL
ALLEGRO_FLIP_VERTICAL
Si no lo queremos volteado, solo ponemos 0.
Y cuando hayamos terminado de dibujar todo a la pantalla, volvemos a poner el valor de la variable "redraw" en 0.
Es muy importante liberar la memoria de nuestro objetos cuando ya no los vayamos a usar.
El código que vamos a tratar será el siguiente:
PHP:
// main.cpp
// Tutorial de programación de juegos en C++ y Allegro 5
#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
ALLEGRO_DISPLAY *display;
ALLEGRO_EVENT_QUEUE *event_queue;
ALLEGRO_TIMER *timer;
ALLEGRO_BITMAP *mi_sprite;
int main()
{
int redraw = 1;
al_init();
al_init_image_addon();
display = al_create_display(640, 480);
event_queue = al_create_event_queue();
timer = al_create_timer(1.0 / 60);
mi_sprite = al_load_bitmap("imagen.png");
al_register_event_source(event_queue, al_get_display_event_source(display));
al_register_event_source(event_queue, al_get_timer_event_source(timer));
al_start_timer(timer);
while (1)
{
ALLEGRO_EVENT event;
al_wait_for_event(event_queue, &event);
if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
break;
if (event.type == ALLEGRO_EVENT_TIMER)
{
redraw = 1;
}
if (redraw)
{
al_clear_to_color(al_map_rgb(0, 0, 0));
al_draw_bitmap(mi_sprite, 10, 10, 0);
al_flip_display();
redraw = 0;
}
}
al_destroy_display(display);
al_destroy_event_queue(event_queue);
al_destroy_timer(timer);
al_destroy_bitmap(mi_sprite);
return 0;
}
En esta lección comenzaremos a usar las variables del tipo ALLEGRO_BITMAP, que son como si fueran los equivalentes a los BITMAP de Allegro 4.4.
PHP:
#include <allegro5/allegro_image.h>
Para usar imágenes en nuestro juego, debemos incluir la librería "allegro_image.h" que servirá para tener a disposición todas las funciones para manipular y dibujar las imagenes o sprites.
PHP:
ALLEGRO_TIMER *timer
Esta variable del tipo ALLEGRO_TIMER será la que se encargará de avisarnos en qué momento debemos actualizar el juego.
PHP:
ALLEGRO_BITMAP *mi_sprite;
Para incluir una imagen o sprite a nuestro juego, debemos declarar una nueva variable del tipo ALLEGRO_BITMAP como un puntero.
PHP:
int redraw = 1;
Declaramos una nueva variable del tipo int que nos servirá para saber en qué momento tenemos que actualizar la pantalla del juego (mientras tenga un valor de 1).
PHP:
al_init_image_addon();
Es muy importante colocar esta función después de "al_init();" si es que queremos usar imágenes en nuestro juego.
PHP:
timer = al_create_timer(1.0 / 60);
Aquí creamos el timer que limitará el FPS de nuestro juego. La función "al_create_timer" toma un argumento, que es cada cuándo se va a recibir un evento de este timer (en segundos), en nuestro caso ponemos 1.0 / 60 si queremos que el juego corra a 60 cuadros por segundo.
PHP:
mi_sprite = al_load_bitmap("imagen.png");
Con esta función (al_load_bitmap) podemos cargar una imagen desde nuestra PC. Puede ser en casi cualquier formato, incluyendo PNG, BMP o TGA.
PHP:
al_register_event_source(event_queue, al_get_timer_event_source(timer));
Para que podamos recibir eventos de nuestro timer, tenemos que registrarlo por medio de las funciones "al_register_event_source" y "al_get_timer_event_source" respectivamente.
PHP:
al_start_timer(timer);
Con esta función iniciamos el timer que limitará el FPS del juego. En nuestro caso le hemos puesto que se ejecute 60 veces por segundo...
PHP:
if (event.type == ALLEGRO_EVENT_TIMER)
{
redraw = 1;
}
Primero, checamos si el evento que recibimos viene de nuestro timer. Si es así, cambiamos el valor de la variable "redraw" a 1.
PHP:
if (redraw)
{
...
al_draw_bitmap(mi_sprite, 10, 10, 0);
...
redraw = 0;
}
Si el valor de la variable "redraw" es mayor a 0, hacemos que la imagen almacenada en mi_sprite se dibuje en pantalla por medio de la función "al_draw_bitmap". Ésta toma 4 argumentos:
El primer argumento toma un objeto del tipo ALLEGRO_BITMAP, en este caso, mi_sprite.
Los siguientes dos argumentos son las coordenadas x,y donde queremos dibujar el sprite.
Y con el último argumento especificamos si queremos dibujar el sprite volteado horizontal o verticalmente. Puede ser una de las dos:
ALLEGRO_FLIP_HORIZONTAL
ALLEGRO_FLIP_VERTICAL
Si no lo queremos volteado, solo ponemos 0.
Y cuando hayamos terminado de dibujar todo a la pantalla, volvemos a poner el valor de la variable "redraw" en 0.
PHP:
al_destroy_timer(timer);
al_destroy_bitmap(mi_sprite);
Es muy importante liberar la memoria de nuestro objetos cuando ya no los vayamos a usar.
Lección 4: Uso del teclado
En esta lección vamos a saber cómo realizar acciones por medio del teclado. En esta parte, aprenderemos cómo mover nuestro sprite (mi_sprite) a cualquier dirección por medio de las flechas del teclado.
El código que trataremos será el siguiente:
Al igual que las lecciones pasadas, este código se basa de la parte anterior, así que solamente explicaré los cambios y los añadidos.
Primero declaramos una enumeración que almacenará los botones o teclas que usaremos en el juego... por el momento solamente usaremos las 4 teclas de dirección.
Después declaramos un "array" o "arreglo" de tipo int con 4 valores iniciados en cero, que nos servirán para checar los botones que estén presionados. Podremos hacer, por ejemplo:
if (key[KEY_LEFT])
Para saber si el botón izquierdo está siendo presionado, justo como en Allegro 4
Para posicionar nuestro sprite adecuadamente tenemos que declarar dos enteros (int) para representar la posición X,Y del jugador respectivamente.
Es muy importante colocar esta función después de "al_init()" si vamos a usar el teclado.
Tal y como lo hicimos con el timer y con el display, para recibir eventos del teclado es necesario registrarlo con la función "al_register_event_source" y "al_get_keyboard_event_source" como argumento.
Tal vez esto puede verse muy complicado a simple vista, pero lo que hace es algo bastante simple. Primero verificamos si el evento que recibimos fue del tipo "ALLEGRO_EVENT_KEY_DOWN", o sea, cuando un botón de nuestro teclado fué presionado. Después checamos si el botón que se presionó fue la tecla izquierda (ALLEGRO_KEY_LEFT), si es así, cambiamos el primer valor del arreglo "key" (KEY_LEFT) a 1. Y hacemos lo mismo con los demás valores (KEY_RIGHT, KEY_UP y KEY_DOWN).
Aquí hacemos prácticamente lo mismo que en la parte anterior, solamente que en vez de checar cuál tecla fue presionada, ahora checamos la tecla que fue soltada por medio del evento ALLEGRO_EVENT_KEY_UP, y volvemos a poner los valores del arreglo "key" a cero.
Aquí actualizamos las coordenadas que nos servirán para posicionar nuestro sprite (en nuestro caso, el "jugador"). Checamos los 4 botones y actualizamos las variables de las coordenadas según sea necesario.
Por último hicimos un pequeño cambio en esta función que dibuja el sprite. Para posicionar el sprite de acuerdo a las coordenadas del jugador debemos cambiar el segundo y tercer argumento por las variables playerX y playerY respectivamente.
El código que trataremos será el siguiente:
PHP:
// main.cpp
// Tutorial de programación de juegos en C++ y Allegro 5
#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
enum GAME_KEYS
{
KEY_LEFT,
KEY_RIGHT,
KEY_UP,
KEY_DOWN
};
int key[] = { 0, 0, 0, 0 };
ALLEGRO_DISPLAY *display;
ALLEGRO_EVENT_QUEUE *event_queue;
ALLEGRO_TIMER *timer;
ALLEGRO_BITMAP *mi_sprite;
int playerX = 0;
int playerY = 0;
int main()
{
int redraw = 1;
al_init();
al_init_image_addon();
al_install_keyboard();
display = al_create_display(640, 480);
event_queue = al_create_event_queue();
timer = al_create_timer(1.0 / 60);
mi_sprite = al_load_bitmap("imagen.png");
al_register_event_source(event_queue, al_get_display_event_source(display));
al_register_event_source(event_queue, al_get_timer_event_source(timer));
al_register_event_source(event_queue, al_get_keyboard_event_source());
al_start_timer(timer);
while (1)
{
ALLEGRO_EVENT event;
al_wait_for_event(event_queue, &event);
if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
break;
if (event.type == ALLEGRO_EVENT_KEY_DOWN)
{
if (event.keyboard.keycode == ALLEGRO_KEY_LEFT)
key[KEY_LEFT] = 1;
if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT)
key[KEY_RIGHT] = 1;
if (event.keyboard.keycode == ALLEGRO_KEY_UP)
key[KEY_UP] = 1;
if (event.keyboard.keycode == ALLEGRO_KEY_DOWN)
key[KEY_DOWN] = 1;
}
if (event.type == ALLEGRO_EVENT_KEY_UP)
{
if (event.keyboard.keycode == ALLEGRO_KEY_LEFT)
key[KEY_LEFT] = 0;
if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT)
key[KEY_RIGHT] = 0;
if (event.keyboard.keycode == ALLEGRO_KEY_UP)
key[KEY_UP] = 0;
if (event.keyboard.keycode == ALLEGRO_KEY_DOWN)
key[KEY_DOWN] = 0;
}
if (event.type == ALLEGRO_EVENT_TIMER)
{
if (key[KEY_LEFT])
playerX -= 4;
if (key[KEY_RIGHT])
playerX += 4;
if (key[KEY_UP])
playerY -= 4;
if (key[KEY_DOWN])
playerY += 4;
redraw = 1;
}
if (redraw)
{
al_clear_to_color(al_map_rgb(0, 0, 0));
al_draw_bitmap(mi_sprite, playerX, playerY, 0);
al_flip_display();
redraw = 0;
}
}
al_destroy_display(display);
al_destroy_event_queue(event_queue);
al_destroy_timer(timer);
al_destroy_bitmap(mi_sprite);
return 0;
}
Al igual que las lecciones pasadas, este código se basa de la parte anterior, así que solamente explicaré los cambios y los añadidos.
PHP:
enum GAME_KEYS
{
KEY_LEFT,
KEY_RIGHT,
KEY_UP,
KEY_DOWN
};
Primero declaramos una enumeración que almacenará los botones o teclas que usaremos en el juego... por el momento solamente usaremos las 4 teclas de dirección.
PHP:
int key[] = { 0, 0, 0, 0 };
Después declaramos un "array" o "arreglo" de tipo int con 4 valores iniciados en cero, que nos servirán para checar los botones que estén presionados. Podremos hacer, por ejemplo:
if (key[KEY_LEFT])
Para saber si el botón izquierdo está siendo presionado, justo como en Allegro 4
PHP:
int playerX = 0;
int playerY = 0;
Para posicionar nuestro sprite adecuadamente tenemos que declarar dos enteros (int) para representar la posición X,Y del jugador respectivamente.
PHP:
al_install_keyboard();
Es muy importante colocar esta función después de "al_init()" si vamos a usar el teclado.
PHP:
al_register_event_source(event_queue, al_get_keyboard_event_source());
Tal y como lo hicimos con el timer y con el display, para recibir eventos del teclado es necesario registrarlo con la función "al_register_event_source" y "al_get_keyboard_event_source" como argumento.
PHP:
if (event.type == ALLEGRO_EVENT_KEY_DOWN)
{
if (event.keyboard.keycode == ALLEGRO_KEY_LEFT)
key[KEY_LEFT] = 1;
if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT)
key[KEY_RIGHT] = 1;
if (event.keyboard.keycode == ALLEGRO_KEY_UP)
key[KEY_UP] = 1;
if (event.keyboard.keycode == ALLEGRO_KEY_DOWN)
key[KEY_DOWN] = 1;
}
Tal vez esto puede verse muy complicado a simple vista, pero lo que hace es algo bastante simple. Primero verificamos si el evento que recibimos fue del tipo "ALLEGRO_EVENT_KEY_DOWN", o sea, cuando un botón de nuestro teclado fué presionado. Después checamos si el botón que se presionó fue la tecla izquierda (ALLEGRO_KEY_LEFT), si es así, cambiamos el primer valor del arreglo "key" (KEY_LEFT) a 1. Y hacemos lo mismo con los demás valores (KEY_RIGHT, KEY_UP y KEY_DOWN).
PHP:
if (event.type == ALLEGRO_EVENT_KEY_UP)
{
if (event.keyboard.keycode == ALLEGRO_KEY_LEFT)
key[KEY_LEFT] = 0;
if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT)
key[KEY_RIGHT] = 0;
if (event.keyboard.keycode == ALLEGRO_KEY_UP)
key[KEY_UP] = 0;
if (event.keyboard.keycode == ALLEGRO_KEY_DOWN)
key[KEY_DOWN] = 0;
}
Aquí hacemos prácticamente lo mismo que en la parte anterior, solamente que en vez de checar cuál tecla fue presionada, ahora checamos la tecla que fue soltada por medio del evento ALLEGRO_EVENT_KEY_UP, y volvemos a poner los valores del arreglo "key" a cero.
PHP:
if (key[KEY_LEFT])
playerX -= 4;
if (key[KEY_RIGHT])
playerX += 4;
if (key[KEY_UP])
playerY -= 4;
if (key[KEY_DOWN])
playerY += 4;
Aquí actualizamos las coordenadas que nos servirán para posicionar nuestro sprite (en nuestro caso, el "jugador"). Checamos los 4 botones y actualizamos las variables de las coordenadas según sea necesario.
PHP:
al_draw_bitmap(mi_sprite, playerX, playerY, 0);
Por último hicimos un pequeño cambio en esta función que dibuja el sprite. Para posicionar el sprite de acuerdo a las coordenadas del jugador debemos cambiar el segundo y tercer argumento por las variables playerX y playerY respectivamente.
Extras
Más tutoriales de Allegro
Nuevo: Plantillas con gestión de escenas
Solución de problemas
Cuando pruebo el juego sin el CodeBlocks, me salta un mensaje de error de que no se pudo encontrar "allegro-5.2.dll" ú otros archivos DLL...
Esto se debe a que seleccionaste el target “Windows Debug” o “Windows Release” cuando compilaste el juego. Estas configuraciones producen ejecutables que requieren los archivos DLL de Allegro. CodeBlocks automaticamente localiza estos archivos, y es por eso que cuando lo pruebas adentro del programa no tira ese error.
Para solucionarlo, simplemente cambia la configuración a “Windows Release (static)” y vuelve a compilar el proyecto. Notarás que el ejecutable de tu juego es más pesado (alrededor de 800 KB o más) pero ya no necesitará los archivos DLL.
También lo puedes hacer desde el menú Build -> Select target.
Esto se debe a que seleccionaste el target “Windows Debug” o “Windows Release” cuando compilaste el juego. Estas configuraciones producen ejecutables que requieren los archivos DLL de Allegro. CodeBlocks automaticamente localiza estos archivos, y es por eso que cuando lo pruebas adentro del programa no tira ese error.
Para solucionarlo, simplemente cambia la configuración a “Windows Release (static)” y vuelve a compilar el proyecto. Notarás que el ejecutable de tu juego es más pesado (alrededor de 800 KB o más) pero ya no necesitará los archivos DLL.
También lo puedes hacer desde el menú Build -> Select target.
Eso es todo por ahora en los tutoriales. Si tienen más dudas pueden mandarme un mensaje por conversación o un mensaje de perfil. Intentaré responder lo más rápido que pueda.
Saludos
Última edición: