Dejar de captar eventos en SDL

Tratamos sobre el manejo de APIs frecuentemente utilizadas en el desarrollo de videojuegos, como SDL, pygame o SFML.

Dejar de captar eventos en SDL

Notapor RafaG » Mié Jul 21, 2010 1:43 pm

Hola, estoy haciendo un juego en C++ con SDL y tengo un problema con los eventos.

En mi juego hay un menú, y para capturar los eventos en el menú uso SDL_WaitEvent(). Una vez puesto lo que es el juego, con la opción "Jugar" del menú que he mencionado, el personaje se puede desplazar por la pantalla, para esto obtengo el estado directamente del teclado (tecla[SDLK_x]).

El problema es que cuando estoy en el juego (en el menú no, en la parte donde el jugador se desplaza) se siguen captando las presiones de tecla del menú. Por lo tanto, si el usuario aprieta la flecha hacia arriba durante el juego (para mover al personaje), cuando regrese al menú automáticamente se apretará la tecla.

He probado cambiando SDL_WaitEvent() por SDL_PollEvent(), no conseguí nada, y también probé a acceder directamente al estado del teclado, pero me daba problemas al intentar salir de un bucle con break.

En el manual que leí de SDL, SDL_PollEvent() guardaba los eventos en una lista, pero no sabía que SDL_WaitEvent() tambien lo hiciese...

¿Cómo lo soluciono?
Gracias, espero haberme explicado bien.
RafaG
 
Mensajes: 20
Registrado: Lun Abr 05, 2010 10:57 am

Notapor Juanxo » Mié Jul 21, 2010 10:53 pm

buenas rafa:

no se como lo tendras organizado, pero si lo tienes mediante clases tipo Screen (algo típico), con tus funciones de Actualizar, Inicializar, Salir, etc para cada tipo de pantalla, lo que puedes hacer al salir de cada menu es vaciar la cola de eventos con el SDL_GetEvent()
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)

Notapor RafaG » Jue Jul 22, 2010 12:46 pm

Juanxo escribió:buenas rafa:

no se como lo tendras organizado, pero si lo tienes mediante clases tipo Screen (algo típico), con tus funciones de Actualizar, Inicializar, Salir, etc para cada tipo de pantalla, lo que puedes hacer al salir de cada menu es vaciar la cola de eventos con el SDL_GetEvent()


He buscado en mis manuales y en Internet y esa función parece no existir.

Aquí está el ejecutable con el código (para Windows): http://www.megaupload.com/?d=YSBU74A0

Y aquí el código:

Código: Seleccionar todo
#include <iostream>
#include <SDL>

void Juego();
void Cargar();
void Salir();

void Mover();
void Imprimir();

SDL_Surface *pantalla, *personaje,*flecha, *menu;
SDL_Rect PosPersonaje,PosFlecha,PosMenu;
SDL_Event evento;
Uint8 *tecla=SDL_GetKeyState(NULL);
int OpcionSeleccionada=1;
int done=0;
int presionado=0;

int main ( int argc, char** argv )
{
    Cargar();
    SDL_BlitSurface(menu,NULL,pantalla,&PosMenu);
    SDL_BlitSurface(flecha,NULL,pantalla,&PosFlecha);
    SDL_Flip(pantalla);
    while (1)
    {
        while (SDL_WaitEvent(&evento))
        {
            if (evento.type==SDL_KEYDOWN)
            {
                if (evento.key.keysym.sym==SDLK_UP)
                {
                    if (OpcionSeleccionada==1)
                    {
                        OpcionSeleccionada=2;
                        PosFlecha.y=205;
                        break;
                    }
                    if (OpcionSeleccionada==2)
                    {
                        OpcionSeleccionada=1;
                        PosFlecha.y=100;
                        break;
                    }
                }
                if (evento.key.keysym.sym==SDLK_DOWN)
                {
                    if (OpcionSeleccionada==1)
                    {
                        OpcionSeleccionada=2;
                        PosFlecha.y=205;
                        break;
                    }
                    if (OpcionSeleccionada==2)
                    {
                        OpcionSeleccionada=1;
                        PosFlecha.y=100;
                        break;
                    }

                }
                if (evento.key.keysym.sym==SDLK_RETURN)
                {
                    if (OpcionSeleccionada==1)
                    {
                        Juego();
                        done=0;
                    }
                    if (OpcionSeleccionada==2)
                    {
                        Salir();
                    }
                }

                if (evento.key.keysym.sym==SDLK_ESCAPE && presionado==0)
                {
                    Salir();
                }
                break;
            }

            SDL_PumpEvents();
            tecla=SDL_GetKeyState(NULL);
            if (tecla[SDLK_ESCAPE]==0)
            {
                presionado=0;
            }

        }

        SDL_BlitSurface(menu,NULL,pantalla,&PosMenu);
        SDL_BlitSurface(flecha,NULL,pantalla,&PosFlecha);
        SDL_Flip(pantalla);
    }
    return 0;
}

void Cargar()
{
    if (SDL_Init(SDL_INIT_VIDEO)<0)
    {
        cerr << "Error: " << SDL_GetError() << endl;
        exit(1);
    }

    atexit(SDL_Quit);

    pantalla=SDL_SetVideoMode(350,350,24,SDL_HWSURFACE | SDL_DOUBLEBUF);
    if (pantalla==NULL)
    {
        cerr << "Error: " << SDL_GetError() << endl;
        exit(1);
    }

    personaje=SDL_LoadBMP("PSN.bmp");
    if (personaje==NULL)
    {
        cerr << "Error: " << SDL_GetError() <<endl>w/2);
    PosPersonaje.y=175-(personaje->h/2);

    flecha=SDL_LoadBMP("FL.bmp");
    if (flecha==NULL)
    {
        cerr << "Error: " << SDL_GetError() << endl;
        exit(1);
    }
    PosFlecha.x=46;
    PosFlecha.y=100;

    menu=SDL_LoadBMP("MN.bmp");
    if (menu==NULL)
    {
        cerr << "Error: " << SDL_GetError() << endl;
        exit(1);
    }
    PosMenu.x=0;
    PosMenu.y=0;

}

void Salir()
{
    SDL_FreeSurface(pantalla);
    SDL_FreeSurface(menu);
    SDL_FreeSurface(flecha);
    SDL_FreeSurface(personaje);
    exit(1);
}

void Juego()
{
    while (done==0)
    {
        Mover();
        Imprimir();
        SDL_Delay(10);
    }
}

void Mover()
{
    SDL_PumpEvents();
    tecla=SDL_GetKeyState(NULL);
    if (tecla[SDLK_UP])
    {
        PosPersonaje.y-=10;
    }
    if (tecla[SDLK_DOWN] && PosPersonaje.y<350-34)
    {
        PosPersonaje.y+=10;
    }
    if (tecla[SDLK_RIGHT]&& PosPersonaje.x<350-34)
    {
        PosPersonaje.x+=10;
    }
    if (tecla[SDLK_LEFT])
    {
        PosPersonaje.x-=10;
    }
    if (tecla[SDLK_ESCAPE]==1)
    {
        presionado=1;
        done=1;
    }
}

void Imprimir()
{
    SDL_FillRect(pantalla,NULL,0);
    SDL_BlitSurface(personaje,NULL,pantalla,&PosPersonaje);
    SDL_Flip(pantalla);
}


Si movéis el personaje hacia abajo, se siguen camptando los eventos del menú, y por lo tanto aparecerá seleccionada otra opción. En mi caso no es "peligroso" para el juego, pero estaría bien saber como solucionar esto para otra ocasión.
RafaG
 
Mensajes: 20
Registrado: Lun Abr 05, 2010 10:57 am

Notapor Juanxo » Jue Jul 22, 2010 4:44 pm

si he entendido bien, cuando tu pulsas para entrar en Juego, se siguen guardando las pulsaciones. El tema seria vaciar la cola de eventos antes de volver al menu.

A grandes rasgos, seria hacer un while (SDL_PollEvent(&event)) al final del juego para vaciar la cola de eventos

PS: perdona por lo de SDL_GetEvent (el nombre creo que es de SFML, la cual te recomiendo) SDL_GetEvent = SDL_PollEvent(&event))
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)

Notapor RafaG » Jue Jul 22, 2010 5:50 pm

Juanxo escribió:si he entendido bien, cuando tu pulsas para entrar en Juego, se siguen guardando las pulsaciones. El tema seria vaciar la cola de eventos antes de volver al menu.

A grandes rasgos, seria hacer un while (SDL_PollEvent(&event)) al final del juego para vaciar la cola de eventos

PS: perdona por lo de SDL_GetEvent (el nombre creo que es de SFML, la cual te recomiendo) SDL_GetEvent = SDL_PollEvent(&event))


Bien, se solucionó, gracias por tu ayuda. Interesante lo de SFML, me informaré.

Hay una cosa que no he logrado comprender, al principio escribí SDL_PollEvent(&event) sin el while. Y no funcionó. No entiendo por qué, al fin y al cabo lo único que hace el while es llamar a la función SDL_PollEvent(), ¿no?
RafaG
 
Mensajes: 20
Registrado: Lun Abr 05, 2010 10:57 am

Notapor Juanxo » Vie Jul 23, 2010 12:44 am

logico, en realidad sdl guarda una cola de eventos (no se si estas familiarizado con las colas) y si solo lo haces una vez, funciona, pero en cuanto tiene mas de un evento, solo quitaria el evento de la cabeza, dejando los demas en la cola
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)


Volver a Sobre las bibliotecas multimedia

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron