Programación para Juegos – Lección 2

05/04/2019Artículo original

Pueden descargar el código fuente de esta lección.

Ahora que ya hemos conseguido mostrar una imagen en pantalla en la segunda parte de la lección 1, vamos a superponer varias imagenes de una manera más eficiente.

//Cabeceras#include "SDL/SDL.h"#include <string>

Estos son los archivos de cabecera para este programa.

Incluimos SDL.h porque obviamente necesitamos funciones de SDL.

//Atributos de la pantallaconst int SCREEN_WIDTH=640;const int SCREEN_HEIGHT=480;const int SCREEN_BPP=32;

Aquí tenemos varios atributos de la pantalla.

Es fácil averiguar para que sirven estos atributos, SCREEN_WIDTH para el ancho de la ventana, y SCREEN_HEIGHT para el alto. SCREEN_BPP son los bits por píxel que tendrá la imagen. Las imágenes que usamos son todas de 32-bit.

//Superficies que vamos a usarSDL_Surface *message = NULL;SDL_Surface *background = NULL;SDL_Surface *screen = NULL;

Estas son las tres imágenes que vamos a usar. background obviamente es la imagen que se verá de fondo, message es la imagen que dice Hello y screen es la ventana contenedora de las imágenes.

SDL_Surface *load_image( std::string filename ){ //Temporary storage for the image that's loaded SDL_Surface* loadedImage= NULL; //The optimized image that will be used SDL_Surface* optimizedImage= NULL;

Esta función es la encargada de cargar la imagen.Lo que hace es cargar la imagen y devolver un puntero a la versión optimizada de la imagen cargada.El argumento filename es la ruta de la imagen a cargar. loadedImage es la superfície que obtenemos cuando la imagen se carga. optimizedImage es la superfície que vamos a usar.

//Cargamos la imagen loadedImage= SDL_LoadBMP( filename.c_str());

Lo primero es cargar la imagen usando SDL_LoadBMP().Pero no se debe usar inmediatamente, ya que esta imagen es de 24-bit y screen es de 32-bit. No es recomendable fusionar imagenes con diferente formato porque SDL tendrá que cambiar el formato en el aire (Durante la ejecución del programa), ralentizándolo.

//Si nada va mal cargando la imagen if( loadedImage != NULL ){ //Create an optimized image optimizedImage= SDL_DisplayFormat( loadedImage ); //Free the old image SDL_FreeSurface( loadedImage );}

Lo siguiente es verificar que la imagen se ha cargado bien. Si ocurre algún error, loadedImage será NULL.

  Programación funcional: Inmutabilidad y funciones puras

Si la imagen se carga correctamente, llamamos a SDL_DisplayFormat() para que cree una nueva versión de loadedImage en el mismo formato que screen. La razón por la que hacemos esto es porque cuando intentamos pegar una imagen en otra de diferente formato, SDL convierte la imagen, así que están en el mismo formato.

Al crear la imagen convertida ganamos en velocidad de ejecución, ya que convertimos la imagen cuando la cargamos, de este modo al aplicar la imagen a screen, ya está en el mismo formato. Por lo tanto SDL no tiene que convertirla en el aire.

Así que ahora tenemos dos imágenes, la imagen cargada antigua (loadedImage), y la nueva imagen optimizada (optimizedImage).

SDL_DisplayFormat() crea una imagen nueva optimizada pero no se deshace de la otra. Por eso hay que llamar a SDL_FreeSurface().

return optimizedImage;}

A continuación, la nueva versión optimizada de la imagen se devuelve.

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination ){ //Make a temporary rectangle to hold the offsets SDL_Rect offset; //Give the offsets to the rectangle offset.x = x; offset.y = y;

Aquí tenemos nuestra función para fusionar las imágenes.Como argumentos tiene las coordenadas donde queremos fusionar la imagen y las dos imágenes.Primero creamos un objeto de tipo SDL_Rect. Hacemos esto porque SDL_BlitSurface() solo acepta este tipo de dato.SDL_Rect es un tipo de dato que representa un rectángulo. Tiene cuatro miembros representando los valores X e Y de un rectángulo (Ancho y alto).

//Fusión de la imagen SDL_BlitSurface( source, NULL, destination, &offset;);}

Con esto vamos a fusionar las imágenes.

  • El primer argumento es la imagen que estamos usando.
  • No os preocupéis por el segundo argumento, por ahora vamos a fijarlo a NULL.
  • El tercer argumento es la imagen que vamos a fusionar.
  • El cuarto argumento contiene la posición en la que se colocará la imagen una vez fusionada.
int main( int argc, char* args[]){

Empezamos con la función principal.

  Cómo Crear Un Bundle Symfony2

Cuando usamos SDL, siempre hay que usar la función main de esta manera:

intmain(intargc,char*args[])// ointmain(intargc,char**args).
//Inicializar todos los subsistemas if( SDL_Init( SDL_INIT_EVERYTHING )== -1 ){return1;}

Usando SDL_Init() iniciamos SDL. A SDL_Init() le pasamos SDL_INIT_EVERYTHING, para que inicie cualquier subsistema de SDL. Los subsistemas SDL son cosas como video, audio, Temporizadores etc, que son componentes individuales usados para hacer juegos.

No vamos a usar todos subsistemas, pero no pasa nada si los inicializamos.

Si SDL no puede inicializarse, devuelve -1, en ese caso controlamos el error devolviendo 1, terminando el programa.

//Configuramos la pantalla screen= SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

Creamos una ventana, lo que nos devuelve un puntero a la misma. Así podremos aplicar las imágenes a la ventana.

Ya conocemos que son los tres primeros argumentos, el cuarto crea la ventana en memoria.

//Si ocurre algún error if(screen== NULL ){return1;}

Si hay algún error al crear la ventana, screen será igual a NULL.

//Título de la ventana SDL_WM_SetCaption("Hello World", NULL );

Fijamos el título de la ventana a Hello World. El segundo argumento es para indicar la ruta del icono de la ventana.

//Cargamos las imágenes message= load_image("hello.bmp");background= load_image("background.bmp");

Cargamos las imágenes usando la función que creamos anteriormente.

//Aplicamos el fondo a la ventana apply_surface(0, 0, background, screen );

Aplicamos el fondo a la ventana con la función que hicimos. Antes de unir el fondo a la ventana, teníamos algo asi:

Pero al unirlas, tendremos algo así:

Cuando las unimos, se copian los píxels de una imagen a otra. Por eso el la imagen que estamos usando de fondo aparece en la esquina superior izquierda, queremos que el fondo ocupe toda la ventana, pero, ¿significa eso que tendremos que cargar la imagen de fondo 3 veces mas?

apply_surface(320, 0, background, screen );apply_surface(0, 240, background, screen );apply_surface(320, 240, background, screen );

No, lo que hacemos es fusionar la misma imagen 3 veces mas.

//Aplicando el mensaje a la ventanaapply_surface(180, 140, message, screen );

Ahora vamos a aplicar la imagen mensaje a la ventana, en las coordenadas X=180 y Y=140

  CSS3: propiedades background-origin y background-clip

El sistema de coordenadas de SDL no trabaja así:

Trabaja así:

El origen de coordenadas (0,0) está en la esquina superior izquierda. Por eso hay que aplicar la imagen de esta forma:

//Actualizando la pantalla if( SDL_Flip( screen )== -1 ){return1;}

Como en la lección anterior, hay que actualizar la patalla para ver las imágenes. Si ocurre algún error devuelve -1, y nosotros devolvemos 1.

//Esperamos 2 seg SDL_Delay(2000);

Llamamos a esta función para que la ventana se muestre durante 2 segundos en pantalla.

//Liberamos las imágenes SDL_FreeSurface( message ); SDL_FreeSurface( background ); //Quit SDL SDL_Quit(); //Return return0;}

Ya que hemos terminado nuestro programa, usamos SDL_FreeSurface() para eliminar de memoria las variables que almacenaban las imágenes. Si no liberamos la memoria, estas variables se quedarán ocupando espacio.

Fuente:

lazyfoo.net

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Contiene enlaces a sitios web de terceros con políticas de privacidad ajenas que podrás aceptar o no cuando accedas a ellos. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad