我想知道如何在 SDL 的 while 循环中检测按键的按下或按键的释放。现在,我知道您可以使用 SDL 获取事件,例如 OnKeyPressed、OnKeyReleased、OnKeyHit 等,但我想知道如何构建像“KeyPressed”这样返回布尔值而不是事件的函数。示例:
while not KeyHit( KEY_ESC )
{
//Code here
}
我知道你已经选择了一个答案..但这里有一些实际代码,说明我通常如何使用一个数组来做到这一点。 :)
首先在某处定义它。
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
然后创建一个keyboard()函数来注册键盘输入
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(如果您有任何问题,请告诉我)
为此有一个 SDL 函数:SDL_GetKeyboardState
检查是否按下左或右 CTRL 键的示例:
const Uint8* state = SDL_GetKeyboardState(nullptr);
if (state[SDL_SCANCODE_LCTRL] || state[SDL_SCANCODE_RCTRL]) {
std::cerr << "ctrl pressed" << std::endl;
}
您应该有 2 个布尔值表作为键。在一张表中,您可以根据 SDL keydown/keyup 事件将键设置为 true 或 false,而在另一张表中,您可以使用 false 进行初始化。检查 keyPressed 时,只需将第二个表键与第一个表键进行比较,如果不同,如果第二个表键为 false,则它被按下,否则它被释放。之后,您执行 secondaryTable[key] := 而不是 secondaryTable[key]。有效!
我在 LuaJIT 和 FFI 中遇到了这个问题,这就是我解决它的方法:
全球:
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 对象,该对象用作数组键,但它需要整数。