我想知道如何在SDL中的while循环中检测按键或释放键。现在,我知道你可以使用像OnKeyPressed,OnKeyReleased,OnKeyHit等SDL获取事件,但我想知道如何构建像'KeyPressed'这样的函数,它返回一个布尔值,而不是一个事件。例如:
while not KeyHit( KEY_ESC )
{
//Code here
}
答案 0 :(得分:11)
我知道你已经选择了一个答案..但这里有一些实际的代码,说明我通常用一个数组做这个。 :)
首先在某处定义。
bool KEYS[322]; // 322 is the number of SDLK_DOWN events
for(int i = 0; i < 322; i++) { // init them all to false
KEYS[i] = false;
}
SDL_EnableKeyRepeat(0,0); // you can configure this how you want, but it makes it nice for when you want to register a key continuously being held down
然后,创建一个键盘()函数,它将注册键盘输入
void keyboard() {
// message processing loop
SDL_Event event;
while (SDL_PollEvent(&event)) {
// check for messages
switch (event.type) {
// exit if the window is closed
case SDL_QUIT:
game_state = 0; // set game state to done,(do what you want here)
break;
// check for keypresses
case SDL_KEYDOWN:
KEYS[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:
KEYS[event.key.keysym.sym] = false;
break;
default:
break;
}
} // end of message processing
}
然后当你真的想要使用键盘输入,即handleInput()函数时,它可能看起来像这样:
void handleInput() {
if(KEYS[SDLK_LEFT]) { // move left
if(player->x - player->speed >= 0) {
player->x -= player->speed;
}
}
if(KEYS[SDLK_RIGHT]) { // move right
if(player->x + player->speed <= screen->w) {
player->x += player->speed;
}
}
if(KEYS[SDLK_UP]) { // move up
if(player->y - player->speed >= 0) {
player->y -= player->speed;
}
}
if(KEYS[SDLK_DOWN]) { // move down
if(player->y + player->speed <= screen->h) {
player->y += player->speed;
}
}
if(KEYS[SDLK_s]) { // shoot
if(SDL_GetTicks() - player->lastShot > player->shotDelay) {
shootbeam(player->beam);
}
}
if(KEYS[SDLK_q]) {
if(player->beam == PLAYER_BEAM_CHARGE) {
player->beam = PLAYER_BEAM_NORMAL;
} else {
player->beam = PLAYER_BEAM_CHARGE;
}
}
if(KEYS[SDLK_r]) {
reset();
}
if(KEYS[SDLK_ESCAPE]) {
gamestate = 0;
}
}
当然,你可以很容易地做你想做的事情
while(KEYS[SDLK_s]) {
// do something
keyboard(); // don't forget to redetect which keys are being pressed!
}
**我网站上的更新版本:** 为了不发布大量源代码,您可以在C ++中查看支持的完整SDL Keyboard类
http://kennycason.com/posts/2009-09-20-sdl-simple-space-shooter-game-demo-part-i.html(如果您有任何问题,请告诉我们)
答案 1 :(得分:0)
你应该有两张布尔表用于钥匙。一个表,您可以根据SDL keydown / keyup事件设置密钥true或false,另一个使用false初始化密钥。检查keyPressed时,只需将第二个表键与第一个表键进行比较,如果不同,如果第二个表键为false,则按下它,否则它被释放。之后,你做secondTable [key]:= not secondTable [key]。作品!
答案 2 :(得分:0)
我在使用FFI的LuaJIT中遇到了这个问题,这就是我解决它的方法:
全局:
KEYS = {}
活动代码:
ev = ffi.new("SDL_Event[1]")
function event()
while sdl.SDL_PollEvent(ev) ~= 0 do
local e = ev[0]
local etype = e.type
if etype == sdl.SDL_QUIT then
return false -- quit
-- os.exit() -- prevents interactive mode
elseif etype == sdl.SDL_KEYDOWN then
if e.key.keysym.sym == sdl.SDLK_ESCAPE then
return false -- quit
-- os.exit()
end
print("Pressed: ", e.key.keysym.scancode, "\n")
KEYS[tonumber(e.key.keysym.sym)] = true
-- print("Pressed: ", (e.key.keysym.sym == sdl.SDLK_w), "\n");
elseif etype == sdl.SDL_KEYUP then
KEYS[tonumber(e.key.keysym.sym)] = false
elseif etype == sdl.SDL_VIDEORESIZE then
-- print("video resize W:".. e.resize.w .. " H:" .. e.resize.h)
width = e.resize.w
height = e.resize.h
onResize()
end
end
return true -- everything ok
end
更新功能:
if KEYS[sdl.SDLK_w] == true then
rot = rot + 1
end
我大部分时间浪费在此:
KEYS[tonumber(e.key.keysym.sym)] = false
因为FFI正在返回一个CData对象,它被用作数组键,但它需要整数。