Ver la versión completa : Duda SDL: pulsación de teclas
Hola, como ya comenté en otro post, estoy realizando pruebas para ir aprendiendo sdl, para cuando venga la gp2x. Voy avanzando y obteniendo resultados, pero me he topado con un problemilla. Al mover al personaje, no me detecta si mantengo la dirección pulsada, sólo me lo mueve una vez, por lo que si quiero moverlo más, tengo que ir pulsando las flechas, por lo que se parece al track & field [wei4] [wei4]
dejo aquí el código, por si alguien me puede sugerir algo:
int Personaje::mover(SDL_Surface *screen)
{
while (SDL_PollEvent(&event))
{
if (teclas [tecla_derecha])
{
x+=10;
if (x>limdcho)
x=limdcho;
return 1;
}
if (teclas [tecla_izquierda])
{
x-=10;
if (x<limizdo)
x=limizdo;
return 1;
}
if (teclas [tecla_arriba])
{
y-=10;
if (y<limsup)
y=limsup;
return 1;
}
if (teclas [tecla_abajo])
{
y+=10;
if (y>liminf)
y=liminf;
return 1;
}
if (teclas [tecla_supr])
return -1;
else
return 0;
}
}
Creo que el problema es que tienes es porque SDL solo te envia eventos cuando pulsas la tecla por primera vez (SDL_KEYDOWN), a partir de ahi ya no te manda mas eventos hasta que sueltes la tecla, en cuyo caso recibiras un evento SDL_KEYUP.
En tu codigo no entiendo muy bien que es ese array teclas[] ?¿?¿?¿?¿
Prueba a usar algo similar a esto:
inc = 1;
if( Event.type == SDL_KEYDOWN )
{
if( Event.key.keysym.sym == SDLK_UP )
yvel += -inc;
if( Event.key.keysym.sym == SDLK_DOWN )
yvel += inc;
if( Event.key.keysym.sym == SDLK_LEFT )
xvel += -inc;
if( Event.key.keysym.sym == SDLK_RIGHT )
xvel += inc;
if( Event.key.keysym.sym == SDLK_ESCAPE )
SystemEnv::Quit();
}
if( Event.type == SDL_KEYUP )
{
if( Event.key.keysym.sym == SDLK_UP )
yvel += inc;
if( Event.key.keysym.sym == SDLK_DOWN )
yvel += -inc;
if( Event.key.keysym.sym == SDLK_LEFT )
xvel += inc;
if( Event.key.keysym.sym == SDLK_RIGHT )
xvel += -inc;
}
posX += xvel;
posY += yvel;
Hola. El motivo de por qué sucede esto no lo sé exactamente porque yo también hace poco que estoy metido en SDL. Supongo que tendrá que ver con cómo maneja la cola de eventos. Pero creo que sí te puedo dar una solución.
La idea es que tengas tantos flags como teclas a detectar que te indicarán si la tecla está pulsada o no. En tu función de actualización del personaje consultarás esos estados y decidirás hacia donde lo quieres desplazar. Por tanto, tu función de detección de teclas quedará más o menos:
if (SDL_PollEvent(&event)
{
case SDL_KEYDOWN:
{
switch(event.key.keysym.sym)
{
case SDLK_LEFT: pulsaIzq = true; break;
case SDLK_RIGHT: pulsaDer = true; break;
case SDLK_UP: pulsaArr = true; break;
case SDLK_DOWN: pulsaAb = true; break;
}
break;
}
case SDL_KEYUP:
{
switch(event.key.keysym.sym)
{
case SDLK_LEFT: pulsaIzq = false; break;
case SDLK_RIGHT: pulsaDer = false; break;
case SDLK_UP: pulsaArr = false; break;
case SDLK_DOWN: pulsaAb = false; break;
}
break;
}
}
Y la que mueve el personaje:
int Personaje::mover(SDL_Surface *screen)
{
if (pulsaIzq)
{
x-=10;
if (x<limizdo) x=limizdo;
}
if (pulsaDer)
{
x+=10;
if (x>limdcho) x=limdcho;
}
(...)
}
Lo que te va a ocurrir es que el personaje probablemente se moverá demasiado rápido (tanto como la CPU sea capaz), así que tendrás que utilizar temporizadores.
NoobLuck
16/11/2005, 22:21
El evento es de pulsación de tecla
He leido que si el sistema tiene repeticion de teclas activada se encolan los SDL keydown.
Tb he visto que hay una función que activa la repetición de teclas:
SDL_KeyboardEvent is a member of the SDL_Event union and is used when an event of type SDL_KEYDOWN or SDL_KEYUP is reported.
The type and state actually report the same information, they just use different values to do it! A keyboard event occurs when a key is released (type=SDK_KEYUP or state=SDL_RELEASED) and when a key is pressed (type=SDL_KEYDOWN or state=SDL_PRESSED). The information on what key was pressed or released is in the keysym structure.
Note: Repeating SDL_KEYDOWN events will occur if key repeat is enabled (see SDL_EnableKeyRepeat).
A mi me pasaba al reves que solo queria una pulsación y no paraba de repetirse a saco mientras mantenia pulsada la tecla, era por la repetición de treclas del sistema, tuve que poner unos flag para evitarlo. Ya pegare el codigo.
No entiendo esto:
while(SDL_PollEvent(&event)){ /* Loop until there are no events left on the queue */
En teoria si no haces nada con los controles el programa dejaria de ejecutarse (la función de vuelve 0 si no hay eventos en cola de ejecución), y en las aplicaciones a veces no pulsas ninguna tecla...
A ver si sale la solución que yo tb estoy empezando y es verdad no esta claro que es esa matriz ...
---
Tralla :musico:
Puck2099
16/11/2005, 22:37
Hola,
Ahora estoy en la facultad y no puedo extenderme mucho, pero échale un vistazo a este hilo (http://www.gp32spain.com/foros/showthread.php?t=23333) donde hay mucha información respecto a las teclas.
Si aun así sigues con problemas, dilo y esta noche me pongo a ver qué podemos hacer :)
Saludos
Ahora estoy en la facultad y no puedo extenderme mucho, pero échale un vistazo a este hilo (http://www.gp32spain.com/foros/showthread.php?t=23333) donde hay mucha información respecto a las teclas.
Alberdi, acabo de probar lo que sugerían en el hilo al que enlaza Puck2099 de usar "SDL_EnableKeyRepeat" en mi código y me ha funcionado de maravilla. Igual con que añadas esa función a tu código tienes suficiente.
Alberdi, acabo de probar lo que sugerían en el hilo al que enlaza Puck2099 de usar "SDL_EnableKeyRepeat" en mi código y me ha funcionado de maravilla. Igual con que añadas esa función a tu código tienes suficiente.
Y el delay hasta que empieza la repeticion no se nota?
Puck2099
16/11/2005, 23:01
Y el delay hasta que empieza la repeticion no se nota?
Ese delay es programable. De todos modos yo lo haría de otra forma, como se ve que lo hice en uno de los últimos posts del hilo que cito.
Saludos
Ese delay es programable. De todos modos yo lo haría de otra forma, como se ve que lo hice en uno de los últimos posts del hilo que cito.
Saludos
Efectivamente, el delay inicial lo decides tú.
Puck2099, en mi programa, con "SDL_EnableKeyRepeat" tengo suficiente porque no utilizo diagonales y no quiero repetición en las teclas, por decirlo de alguna manera, de acción, que es lo que entiendo que no te funcionaba. Pero bueno, tu solución utilizando la variable "pausa" me parece también una buena idea. Está bien saberlo.
Bueno, ya está solucionado. sólo hacía falta incluir esta línea:
SDL_EnableKeyRepeat(30, 30);
y así detecta que el botón se mantiene pulsado. Gracias a todos por ayudar.
Edito: yo también estoy haciendo pruebas, por lo que en estos momentos esta solución me vale. Además, la gp2x no tenía 8 posiciones del joystick? Por lo tanto, la diagonal será como una tecla, supongo.
Yo nunca he usado el enablekeyrepeat, de hecho lo hago tal q asi:
while( ! terminar ){
SDL_PollEvent(NULL);
teclas = SDL_GetKeyState(NULL);
if( teclas[SDLK_ESCAPE] ) terminar = 1;
if(teclas[SDLK_LEFT]) MovimientoIzquierda();
if(teclas[SDLK_RIGHT]) MovimientoDerecha();
if(teclas[SDLK_UP]) MovimientoArriba();
if(teclas[SDLK_DOWN]) MovimientoAbajo();
}
Y nunca me ha fallado, de hecho cuando sueltas la tecla deja de moverse, como debe ser (bueno en mi caso claro xD)
Yo nunca he usado el enablekeyrepeat, de hecho lo hago tal q asi:
while( ! terminar ){
SDL_PollEvent(NULL);
teclas = SDL_GetKeyState(NULL);
if( teclas[SDLK_ESCAPE] ) terminar = 1;
if(teclas[SDLK_LEFT]) MovimientoIzquierda();
if(teclas[SDLK_RIGHT]) MovimientoDerecha();
if(teclas[SDLK_UP]) MovimientoArriba();
if(teclas[SDLK_DOWN]) MovimientoAbajo();
}
Y nunca me ha fallado, de hecho cuando sueltas la tecla deja de moverse, como debe ser (bueno en mi caso claro xD)
Este es el que uso yo y va de perlas...
Pero lo que no me gusta de tu forma de hacerlo es q si apretas la derecha y la izquiera a la vez, hace dos desplazamientos para nada?
iria bien algo asi:
if(teclas[SDLK_LEFT] XOR teclas[SDLK_RIGHT])
{
if(teclas[SDLK_LEFT]) MovimientoIzquierda();
if(teclas[SDLK_RIGHT]) MovimientoDerecha();
}
lo del XOR me lo inventao yo, pero lo puedes implementar asi:
if(!((teclas[SDLK_LEFT] && teclas[SDLK_RIGHT]) ||
!(teclas[SDLK_LEFT] || teclas[SDLK_RIGHT])))
Puck2099
17/11/2005, 02:13
Pero lo que no me gusta de tu forma de hacerlo es q si apretas la derecha y la izquiera a la vez, hace dos desplazamientos para nada?
Pero es que esos movimientos son excluyentes, ¿no? :p
NoobLuck
18/11/2005, 09:23
A mi no me iba, y ahora me va perfectamete. Me pasaba al contrario que me pillaba un monton de eventos. Indagando he visto que tb conviene ignorar os eventos que no se utilizan, como vienen a ser el raton etc.
Lo que yo he hecho es un programa sencillo que abre fotos (siguiendo la introducción).
Tb destacar que al hacer GUIs conviene no activar la reptición de tecla, usar WaitEvent en vez de PollEvent y situar el bucle de ejecucion principal en el while pues el programa lo unico que hace despues de abrir la foto es esperar eventos (espera acciones del usuario).
Ademas yo ignoro los eventos que no se utilizan para nada, asi si paso el raton por delante de la ventana no consumo recursos :arriba:.
#include "stdlib.h"
#include "SDL.h"
void ignore_event(){
/*Ignore unused events*/
SDL_EventState(SDL_KEYUP, SDL_IGNORE);
SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE);
SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE);
SDL_EventState(SDL_JOYAXISMOTION, SDL_IGNORE);
SDL_EventState(SDL_JOYBALLMOTION, SDL_IGNORE);
SDL_EventState(SDL_JOYHATMOTION, SDL_IGNORE);
SDL_EventState(SDL_JOYBUTTONDOWN, SDL_IGNORE);
SDL_EventState(SDL_JOYBUTTONUP, SDL_IGNORE);
SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
}
void events(){
SDL_Event event;
while (SDL_WaitEvent(&event)){ /*Waits for an event*/
switch (event.type){
case SDL_KEYDOWN:
switch(event.key.keysym.sym){
case SDLK_q: exit(0);
default: break;
}/* switch "event.key.keysym.sym" */
break;
case SDL_QUIT: exit(0);
}/* switch "event.type" */
}
}
Es el fichero del programa donde guardo la función con los eventos.
------------------------------------
:fieston:
¡¡¡Fiesta de eventos con el Poll_Master!!!
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.