如何正确检测 sdl2 中的按键按下和释放
Posted
技术标签:
【中文标题】如何正确检测 sdl2 中的按键按下和释放【英文标题】:How to correctly detect key press and release in sdl2 【发布时间】:2017-01-31 02:05:22 【问题描述】:我的完整代码-
#include <SDL.h>
#include <SDL_opengl.h>
#include <GL\GLU.h>
#include <fstream>
using namespace std;
int index = 0;
int speed = 0;
int frames = 0;
int lasttime = 0;
int mousex = 0;
int mousey = 0;
bool postRedraw = true;
int screenWidth = 640;
int screenHeight = 480;
float screenAspect = screenWidth/screenHeight;
bool init();
bool initGL();
void handleKeys( unsigned char key, int x, int y );
void update();
void render();
void close();
void Initialize();
void handleEvents();
ofstream logFile;
SDL_Window* gWindow = NULL;
bool isRunning = true;
SDL_GLContext gContext;
float xpos = 0.0;
float ypos = 0.0;
float zpos = 0.0;
void Initialize()
gluPerspective(60.0f, screenAspect, 1.0, 400.0);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
glTranslatef(0.0f, 0.0f, -5.0f);
glFrontFace(GL_CCW);
glEnable(GL_LIGHT0);
void render()
glTranslatef(xpos, ypos, zpos);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_TRIANGLES);
glVertex3f(-1.0f,0.0f,-1.0f);
glVertex3f(0.0f, 1.0f, -1.0f);
glVertex3f(0.0f, 2.0f, -2.0f);
glEnd();
postRedraw = true;
void handleEvents()
const Uint8* keystates = SDL_GetKeyboardState(NULL);
if(keystates[SDL_GetScancodeFromKey(SDLK_w)])
zpos += 0.01;
if(keystates[SDL_GetScancodeFromKey(SDLK_s)])
zpos -= 0.01;
else
bool init()
bool success = true;
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
logFile<<"SDL could not initialize! SDL Error: "<<SDL_GetError()<<endl;
success = false;
else
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screenWidth, screenHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
if( gWindow == NULL )
logFile<<"Window could not be created! SDL Error: "<<SDL_GetError()<<endl;
success = false;
else
gContext = SDL_GL_CreateContext( gWindow );
if( gContext == NULL )
logFile<<"OpenGL context could not be created! SDL Error: "<<SDL_GetError()<<endl;
success = false;
else
if( SDL_GL_SetSwapInterval( 1 ) < 0 )
logFile<<"Warning: Unable to set VSync! SDL Error: "<<SDL_GetError()<<endl;
if( !initGL() )
logFile<<"Unable to initialize OpenGL!"<<endl;
success = false;
logFile.open("log.txt");
if(logFile.is_open())
success = true;
else
success = false;
return success;
bool initGL()
bool success = true;
GLenum error = GL_NO_ERROR;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
error = glGetError();
if( error != GL_NO_ERROR )
logFile<<"Error initializing OpenGL! "<<gluErrorString( error )<<endl;
success = false;
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
error = glGetError();
if( error != GL_NO_ERROR )
logFile<<"Error initializing OpenGL! "<<gluErrorString( error )<<endl;
success = false;
glClearColor( 0.f, 0.f, 0.f, 1.f );
error = glGetError();
if( error != GL_NO_ERROR )
logFile<<"Error initializing OpenGL! "<<gluErrorString( error );
success = false;
return success;
void close()
logFile.close();
SDL_DestroyWindow( gWindow );
gWindow = NULL;
SDL_Quit();
int main( int argc, char* args[] )
if( !init() )
logFile<<"Failed to initialize!"<<endl;
else
SDL_Event event;
Initialize();
lasttime = SDL_GetTicks();
while(isRunning)
while( SDL_PollEvent( &event ) != 0 )
if(event.type == SDL_QUIT)
isRunning = false;
else if(event.type == SDL_MOUSEMOTION)
SDL_GetMouseState(&mousex, &mousey);
else if(event.type == SDL_MOUSEBUTTONDOWN)
SDL_GetMouseState(&mousex, &mousey);
else if(event.type == SDL_MOUSEBUTTONUP)
SDL_GetMouseState(&mousex, &mousey);
handleEvents();
if(postRedraw)
postRedraw = false;
render();
SDL_GL_SwapWindow( gWindow );
if((SDL_GetTicks()-lasttime)>=1000)
lasttime = SDL_GetTicks();
speed = frames;
logFile<<speed<<endl;
frames = 0;
else
frames++;
close();
return 0;
以上代码仅用于测试,我有问题的简约代码是-
void handleEvents()
const Uint8* keystates = SDL_GetKeyboardState(NULL);
if(keystates[SDL_GetSancodeFromKey(SDLK_w)])
zpos += 0.01;
if(keystates[SDL_GetScancodeFromKey(SDLK_s)])
zpos -= 0.01;
else
预期: 按下 w/s 键时,绘制的三角形将向前/向后移动。
输出: 即使松开按键,三角形也会继续向所需方向移动。
【问题讨论】:
建议放弃最后两个问题,因为它们不相关,并且使这个问题过于宽泛,更有可能被关闭。如果您真的对它们的答案感兴趣,请再问两个问题。 这是错字吗?const Uint8* keystates = SDL_GetKeyboardState(NULL);
这里没有if
,但是在更大的代码块中有一个if
。
那是错误的,我更新了我的问题
【参考方案1】:
随着时间的推移,你会累积你的矩阵变化。 glTranslatef
通过平移修改 current 矩阵。下一帧它再次修改它。再一次,....
您应该使用glLoadIdentity()
调用重置矩阵。请注意,它会修改当前选定的矩阵,并将撤消您在Initialize
中所做的矩阵更改(至少在这里您的glTranslatef
- 透视图应该转到GL_PROJECTION
矩阵,您还没有这样做)。
【讨论】:
以上是关于如何正确检测 sdl2 中的按键按下和释放的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 QxtGlobalShortcut 库检测 Qt 中的按键释放事件