Al igual que en el tutorial anterior, tenemos dividido el código fundamentalmente en la cabecera (.h) y la implementacion (.cpp). Con respecto al anterior tutorial, la cabecera prácticamente no ha cambiado, donde antes ponía Demo_1, ahora pone Demo_2, a si que os la dejo aquí para copiar pero doy por hecha la explicación.
#ifndef DEMO_2_H_ #define DEMO_2_H_ #include "SDL2/SDL.h" class Demo_2 { private: bool running; SDL_Window* mainwindow; static const uint32_t WIN_HEIGHT = 512; //px static const uint32_t WIN_WIDTH = 512; //px public: Demo_2(); int Execute(){ return OnExecute(); } bool Init(){ return OnInit(); } void Loop(){ return OnLoop(); } void Render(){ return OnRender(); } void Cleanup(){ return OnCleanup(); } void Event(SDL_Event* Event){ OnEvent(Event); } int OnExecute(); bool OnInit(); void OnEvent(SDL_Event* Event); void OnLoop(); void OnRender(); void OnCleanup(); }; #endif
#include "Demo_2.h" #include <iostream> Demo_2::Demo_2() : running(false), mainwindow(NULL) {} void Demo_2::OnEvent(SDL_Event* event) { switch (event->type) { case SDL_MOUSEBUTTONUP: std::cout << "MOUSE_BUTTON_UP: x:" << event->button.x << "| y:" << event->button.y << "| button1:" << (event->button.button == SDL_BUTTON_LEFT) << "| button2:" << (event->button.button == SDL_BUTTON_RIGHT) << "| button3:" << (event->button.button == SDL_BUTTON_MIDDLE) << "| clickState:" << event->motion.state << std::endl << std::endl; break; case SDL_MOUSEBUTTONDOWN: std::cout << "MOUSE_BUTTON_DOWN: x:" << event->button.x << "| y:" << event->button.y << "| button1:" << (event->button.button == SDL_BUTTON_LEFT) << "| button2:" << (event->button.button == SDL_BUTTON_RIGHT) << "| button3:" << (event->button.button == SDL_BUTTON_MIDDLE) << "| clickState:" << event->motion.state << std::endl << std::endl; break; case SDL_MOUSEMOTION: std::cout << "MOUSE_MOTION: x:" << event->motion.x << "| y:" << event->motion.y << "| xrel:" << event->motion.xrel << "| yrel:" << event->motion.yrel << "| clickState:" << event->motion.state << "| button1:" << ((event->motion.state & 1) == 1) << "| button2:" << ((event->motion.state & 4) == 4) << "| button3:" << ((event->motion.state & 2) == 2) << std::endl << std::endl; break; case SDL_KEYUP: running = event->key.keysym.sym != SDLK_ESCAPE; break; case SDL_QUIT: running = false; break; default: break; } } void Demo_2::OnLoop() {} void Demo_2::OnRender() {} void Demo_2::OnCleanup() { SDL_DestroyWindow(mainwindow); SDL_Quit(); } bool Demo_2::OnInit() { if(SDL_Init(SDL_INIT_EVERYTHING) < 0) return false; mainwindow = SDL_CreateWindow("Titulo de la Ventana", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIN_WIDTH, WIN_HEIGHT, SDL_WINDOW_SHOWN); if(!mainwindow) return false; running = true; return true; } int Demo_2::OnExecute() { if (!Init()) return -1; SDL_Event event; while (running) { while (SDL_PollEvent(&event)) Event(&event); Loop(); Render(); } Cleanup(); return 0; }
Los principales cambios se han producido en OnExecute y en OnEvent.
- OnExecute: Hemos quitado el contador de 10 vueltas y ahora tenemos un objeto del tipo SDL_Event para capturar los eventos.
Después tenemos igual que antes el bucle en el que tenemos la función Loop y Render y al principio hemos añadido otro bucle. Este bucle se encarga de sacar todos los eventos (SDL_PollEvent) que se han producido en esa vuelta de bucle y los envía a la función Event para tratar. Si os fijáis, lo que hacemos es pasarle el puntero al evento, por eso el PollEvent puede guardar en tu estructura el evento.
Por lo demás el OnExecute no tiene mucho más que comentar. - OnEvent: Recibimos un evento, ¿Que forma tiene un evento?
Según la página oficial esta es su representación de evento.typedef union{ Uint8 type; SDL_ActiveEvent active; SDL_KeyboardEvent key; SDL_MouseMotionEvent motion; SDL_MouseButtonEvent button; SDL_JoyAxisEvent jaxis; SDL_JoyBallEvent jball; SDL_JoyHatEvent jhat; SDL_JoyButtonEvent jbutton; SDL_ResizeEvent resize; SDL_ExposeEvent expose; SDL_QuitEvent quit; SDL_UserEvent user; SDL_SywWMEvent syswm; } SDL_Event;
typedef struct{ Uint8 type; Uint8 state; SDL_keysym keysym; } SDL_KeyboardEvent;
Para los que no sepan lo que es, una Union hace que todo lo que este dentro de las llaves ocupe la misma posición de memoria, dependiendo del tipo de evento se rellenan mas o menos bits. Esto que han hecho es una especie de simulación de herencia o interfaz para struct. La explicación se ha quedado un poco pobre, si no te ha quedado claro mira en Internet que encontraras mucha información.
Por ello lo primero que hace la función OnEvent es mirar que tipo de evento estamos tratando, para ello hacemos un switch con el type del evento.
Hemos capturado 5 tipos como ejemplo, aquí podéis encontrar todos (Input Events):
http://wiki.libsdl.org/APIByCategory
Después de capturar el tipo de evento accedemos al tipo de evento correspondiente en la estructura, por ejemplo: event->button Y a la propiedad que deseemos, SDL_MOUSEBUTTONUP al ser un evento de ratón podemos capturar la posicion x e y, el botón del ratón que se ha liberado (lógicamente solo puede ser uno a la vez, por muy rápidos que seamos es casi imposible liberar dos a la vez) y el estado en el que está el ratón.
En el caso de mousemotion existen xrel e yrel que te dan la posición relativa a la anterior posición del ratón. El caso del estado te da información acerca de que botones están pulsados con una mascara binaria, para poder obtener cuales están pulsados utilizo la & binaria y no la && lógica. He comprobado que obtiene hasta 5 botones del ratón en mi caso. Imagino que no dependerá del ratón, a si que, si quieren mas botones de ratón que se los bindeen a teclas especiales :P.
Para ejemplificar el teclado he puesto que cuando se presiona la tecla Escape (Esc) se termine el programa. Esa porción de código es suficientemente simple, no me paro más.
Por ultimo SDL_QUIT corresponde al evento de hacer click en la X de la ventana, también salimos del programa. Si no lo configuramos, no podremos salir dándole a la X.
Para probar el ejemplo igual que en el anterior, crearos un main con un objeto del tipo Demo_2 y llamad a Execute(). Deberiais tener una ventana y una traza en la consola de los eventos que hemos capturado, el mouse motion y el mouse click no se capturan si no estas encima de la ventana.
Aquí se termina este tutorial, espero os haya sido útil. Os dejo un enlace a la documentación de la API, en el apartado Input Events aparecen todos los eventos: http://wiki.libsdl.org/APIByCategory
Aquí se termina este tutorial, espero os haya sido útil. Os dejo un enlace a la documentación de la API, en el apartado Input Events aparecen todos los eventos: http://wiki.libsdl.org/APIByCategory
No hay comentarios:
Publicar un comentario