SDL 2 Lecciones: Lección 3 - Eventos

Hola a todos! Esta es la tercera lección en SDL 2. La información se toma de esta fuente. No me gustaron los tutoriales de manejo de eventos de Lasy Foo, así que escribiré los míos, pero el material se puede encontrar aquí y aquí .

Y comenzamos, bienvenidos a la lección.

Eventos


Hoy enseñaremos nuestro programa para responder a eventos con la ayuda de John .

Entonces comencemos. conecta SDL 2 y crea 3 variables globales y 2 constantes.

#include <SDL2/SDL.h> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *john = NULL; 

A continuación, escribimos 3 funciones ya conocidas de la última lección:

Init
 int init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init: " << SDL_GetError() << std::endl; system("pause"); return 1; } win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; system("pause"); return 1; } scr = SDL_GetWindowSurface(win); return 0; } 

Carga
 int load() { john = SDL_LoadBMP("john.bmp"); if (john == NULL) { std::cout << "Can't load image: " << SDL_GetError() << std::endl; system("pause"); return 1; } return 0; } 

Salir
 int quit() { SDL_FreeSurface(john); SDL_DestroyWindow(win); SDL_Quit(); return 0; } 


Atención (!), Si copia el código de la lección anterior, no olvide cambiar la sonrisa a John .

Todo lo que debería decirse: decidí mostrar errores en la etapa de inicialización y carga de imágenes.

Entonces, continuemos. abra main y llame a las funciones Init y Load .

 int main (int argc, char ** args) { if (init() == 1) { return 1; } if (load() == 1) { return 1; } } 

Ahora veamos cómo funciona cualquier aplicación. Cualquier programa que ejecute (Google Chrome, Paint, Minecraft) tiene un bucle principal que se ejecuta una gran cantidad de veces. Esto es necesario para el dinamismo. Anteriormente, escribimos un programa que solo mostraba una sonrisa durante 2 segundos, pero para que el programa aprenda a responder a las acciones del usuario (o al menos muestre la imagen sin cesar), necesita un bucle While .

Se repetirá constantemente y en él ya podemos hacer lo que queramos, por ejemplo, procesar eventos. Pero antes de comenzar el ciclo de glan, creemos algunas variables.

  bool run = true; SDL_Event e; SDL_Rect r; int x = 0; int y = 0; rx = x; ry = y; 

Analizaremos todo ahora. Primero, cree una variable de ejecución de tipo boolean . Esta variable es responsable de la ejecución del bucle: mientras el programa se está ejecutando, es cierto , si queremos detener la ejecución, establezca esta variable en falso . A continuación, cree un objeto e de la clase SDL_Event . Las propiedades de este objeto contendrán los datos del evento recibido, además serán más detallados. Después de eso creamos un objeto r de la clase SDL_Rect . Este es el rectángulo requerido para dibujar el objeto con algunas coordenadas que necesitamos. Luego creamos variables x e y de tipo int . Asigne inmediatamente sus valores a cero. Estas serán las coordenadas de nuestro personaje. Al siguiente elemento, asignamos las variables rx y ry los valores x e y, respectivamente. rx y ry son las coordenadas del rectángulo r .

Es hora de abrir el ciclo principal.

  while (run) { while(SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { run = false; } if (e.type == SDL_KEYDOWN) { if (e.key.keysym.sym == SDLK_UP) { y -= 1; } if (e.key.keysym.sym == SDLK_DOWN) { y += 1; } if (e.key.keysym.sym == SDLK_RIGHT) { x += 1; } if (e.key.keysym.sym == SDLK_LEFT) { x -= 1; } } } rx = x; ry = y; SDL_FillRect(scr, NULL, SDL_MapRGB(scr -> format, 255, 255, 255)); SDL_BlitSurface(john, NULL, scr, &r); SDL_UpdateWindowSurface(win); } 

Analicemos este código. Tenemos dos ciclos El primero principal es el principal, que funciona ejecutando variable, como se mencionó anteriormente. El segundo ciclo es responsable de manejar los eventos.

La función SDL_PollEvent () abre la cola de eventos recibidos en una ejecución del bucle principal, elimina el último evento y escribe datos sobre este evento en las variables del objeto que pasamos a esta función, tenemos esta e . Esta función devuelve 0, NULL o false si todos los eventos de la cola se han eliminado, por lo que escribimos la condición while (SDL_PollEvent (& e)! = NULL) .

Miramos más allá: la primera comprobación que tenemos es hacer clic en la cruz en el marco de la ventana. Si hacemos clic en él, a la variable tipo del objeto e se le asigna el valor SDL_QUIT . Si esto sucede, asignamos falso a la variable de ejecución y el ciclo termina.

Luego, escribí una prueba de teclado. Si se presiona el botón, la variable e.type es igual a SDL_KEYDOWN . A continuación, verifique los valores clave. La variable e.key.keysym.sym almacena el valor del botón. Comparamos este valor con el deseado y realizamos ciertas acciones. Vamos a cambiar la coordenada de John. Si se presiona la flecha hacia arriba, y disminuye en 1, si hacia abajo, aumenta, etc. Creo que entiendes el punto.

Después de procesar los eventos, reasigne rx y ry para actualizar las coordenadas del Hombre. A continuación, escribimos la función ya conocida SDL_FilRect , tiene un papel muy importante. Si no lo hubiéramos escrito, John habría dejado una marca fea en el movimiento, y así, cada cuadro dibujamos un fondo blanco y dibujamos un sprite encima. Después de eso, dibujamos a nuestro héroe con la función SDL_BlitSurface . Aquí usaremos nuestro rectángulo r , o más bien sus variables x e y , para dibujar no solo en la parte superior izquierda, sino con algunas coordenadas necesarias. A continuación, solo actualice la ventana.

Después del bucle principal, escriba return quit (); para completar el programa

Eso es todo, esta lección ha terminado. Aquí hay un código de este tipo:

Código
 #include <SDL2/SDL.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *john = NULL; int init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init: " << SDL_GetError() << std::endl; system("pause"); return 1; } win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; system("pause"); return 1; } scr = SDL_GetWindowSurface(win); return 0; } int load() { john = SDL_LoadBMP("john.bmp"); if (john == NULL) { std::cout << "Can't load image: " << SDL_GetError() << std::endl; system("pause"); return 1; } return 0; } int quit() { SDL_FreeSurface(john); SDL_DestroyWindow(win); SDL_Quit(); return 0; } int main (int argc, char ** args) { if (init() == 1) { return 1; } if (load() == 1) { return 1; } bool run = true; SDL_Event e; SDL_Rect r; int x = 0; int y = 0; rx = x; ry = y; while (run) { while(SDL_PollEvent(&e) != NULL) { if (e.type == SDL_QUIT) { run = false; } if (e.type == SDL_KEYDOWN) { if (e.key.keysym.sym == SDLK_UP) { y -= 1; } if (e.key.keysym.sym == SDLK_DOWN) { y += 1; } if (e.key.keysym.sym == SDLK_RIGHT) { x += 1; } if (e.key.keysym.sym == SDLK_LEFT) { x -= 1; } } } rx = x; ry = y; SDL_FillRect(scr, NULL, SDL_MapRGB(scr -> format, 255, 255, 255)); SDL_BlitSurface(john, NULL, scr, &r); SDL_UpdateWindowSurface(win); } return quit(); } 


Y les digo adiós, ¡adiós a todos!

<< Lección anterior || Próxima lección >>

Source: https://habr.com/ru/post/455577/


All Articles