Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用SDL一次处理多个按键? 使用C++对ubuntu上的SDL编程,使自己熟悉OpenGL编程。经过一些环顾四周和试验,我开始明白了。我需要关于SDL键盘事件处理的建议_C++_Linux_Opengl_Ubuntu_Sdl - Fatal编程技术网

如何使用SDL一次处理多个按键? 使用C++对ubuntu上的SDL编程,使自己熟悉OpenGL编程。经过一些环顾四周和试验,我开始明白了。我需要关于SDL键盘事件处理的建议

如何使用SDL一次处理多个按键? 使用C++对ubuntu上的SDL编程,使自己熟悉OpenGL编程。经过一些环顾四周和试验,我开始明白了。我需要关于SDL键盘事件处理的建议,c++,linux,opengl,ubuntu,sdl,C++,Linux,Opengl,Ubuntu,Sdl,我有一个第一人称相机,可以向前走,向后走,左右扫射,用鼠标环顾四周,这很好。以下是我的processEvents函数: void processEvents() { int mid_x = screen_width >> 1; int mid_y = screen_height >> 1; int mpx = event.motion.x; int mpy = event.motion.y; float angle_y = 0.0f; float angle_

我有一个第一人称相机,可以向前走,向后走,左右扫射,用鼠标环顾四周,这很好。以下是我的processEvents函数:

void processEvents()
{
    int mid_x = screen_width  >> 1;
int mid_y = screen_height >> 1;
int mpx = event.motion.x;
int mpy = event.motion.y;
float angle_y  = 0.0f;
float angle_z  = 0.0f;

while(SDL_PollEvent(&event))
{
    switch(event.type)
    {
        case SDL_KEYDOWN:
            switch(event.key.keysym.sym)
            {
                case SDLK_ESCAPE:
                    quit = true;
                    break;
                case SDLK_w:
                    objCamera.Move_Camera( CAMERASPEED);
                    break;
                case SDLK_s:
                    objCamera.Move_Camera(-CAMERASPEED);
                    break;
                case SDLK_d:
                    objCamera.Strafe_Camera( CAMERASPEED);
                    break;
                case SDLK_a:
                    objCamera.Strafe_Camera(-CAMERASPEED);
                    break;
                default:
                    break;
            }
            break;

        case SDL_MOUSEMOTION:
            if( (mpx == mid_x) && (mpy == mid_y) ) return;

            SDL_WarpMouse(mid_x, mid_y);

            // Get the direction from the mouse cursor, set a resonable maneuvering speed
            angle_y = (float)( (mid_x - mpx) ) / 1000;      
            angle_z = (float)( (mid_y - mpy) ) / 1000;

            // The higher the value is the faster the camera looks around.
            objCamera.mView.y += angle_z * 2;

            // limit the rotation around the x-axis
            if((objCamera.mView.y - objCamera.mPos.y) > 8)  objCamera.mView.y = objCamera.mPos.y + 8;
            if((objCamera.mView.y - objCamera.mPos.y) <-8)  objCamera.mView.y = objCamera.mPos.y - 8;

            objCamera.Rotate_View(-angle_y);

            break;

        case SDL_QUIT:
            quit = true;
            break;

        case SDL_VIDEORESIZE:
            screen = SDL_SetVideoMode( event.resize.w, event.resize.h, screen_bpp, SDL_OPENGL | SDL_HWSURFACE | SDL_RESIZABLE | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE );
            screen_width = event.resize.w;
            screen_height = event.resize.h;
            init_opengl();
            std::cout << "Resized to width: " << event.resize.w << " height: " << event.resize.h << std::endl;
            break;

        default:
            break;
    }
}
}
void processEvents()
{
int mid_x=屏幕宽度>>1;
int mid_y=屏幕高度>>1;
int mpx=event.motion.x;
int-mpy=event.motion.y;
浮动角度_y=0.0f;
浮动角度_z=0.0f;
while(SDL_事件和事件))
{
开关(事件类型)
{
案例SDL_按键关闭:
开关(event.key.keysym.sym)
{
案例SDLK_逃生:
退出=真;
打破
案例SDLK\U w:
移动摄像机(摄像机速度);
打破
案例SDLK_s:
移动相机(-CAMERASPEED);
打破
案例SDLK\U d:
目标照相机。扫射照相机(照相机速度);
打破
案例SDLK_a:
扫射照相机(-CAMERASPEED);
打破
违约:
打破
}
打破
案例SDL_:
if((mpx==mid_x)和&(mpy==mid_y))返回;
SDL_鼠标(中x、中y);
//从鼠标光标获取方向,设置合理的操纵速度
角度y=(浮动)((中间x-mpx))/1000;
角度z=(浮动)((中间y-mpy))/1000;
//该值越高,摄影机环视四周的速度越快。
objCamera.mView.y+=角度_z*2;
//限制绕x轴旋转
如果((objCamera.mView.y-objCamera.mPos.y)>8)objCamera.mView.y=objCamera.mPos.y+8;

如果((objCamera.mView.y-objCamera.mPos.y)不只是查看keydown事件,任何一次关注多个关键点的解决方案都必须同时查看keydown和keydup事件,并跟踪相关关键点的状态

因此,代替(伪代码):

相反,您会有更像(同样是伪代码)的东西:


然后,
updateMovement
例程将查看
keystates
,并根据所有移动键的状态计算出一个组合移动。

SDL跟踪所有键的当前状态。您可以通过以下方式访问此状态:


因此,每次迭代都可以根据按键状态更新移动。要使移动平稳,应根据更新之间经过的时间更新移动幅度。

一个好方法是编写一个键盘(“输入”)处理程序,该处理程序将处理输入事件,并将事件的状态保持在某种结构中(关联数组听起来不错-键[keyCode])

每次键盘处理程序接收到“按键按下”事件时,它都会将按键设置为已启用(true),而当它接收到按键按下事件时,它会将其设置为已禁用(false)

然后,您可以一次检查多个键,而无需直接拉取事件,并且您将能够在整个帧上重复使用键盘,而无需将其传递给子例程

一些快速伪代码:

class KeyboardHandler {
    handleKeyboardEvent(SDL Event) {
        keyState[event.code] = event.state;
    }

    bool isPressed(keyCode) {
        return (keyState[keyCode] == PRESSED);
    }

    bool isReleased(keyCode) {
        return (keyState[keyCode] == RELEASED);
    }

    keyState[];
}

...

while(SDL Pull events)
{
    switch(event.type) {
        case SDL_KEYDOWN:
        case SDL_KEYUP:
                keyHandler.handleKeyboardEvent(event);
            break;
        case SDL_ANOTHER_EVENT:
                ...
            break;
    }   
}

// When you need to use it:
if(keyHandler.isPressed(SOME_KEY) && keyHandler.isPressed(SOME_OTHER_KEY))
    doStuff(TM);

使用获取键盘状态

如果使用SDL2,则使用

例如:

const Uint8 *keyboard_state_array = SDL_GetKeyboardState(NULL);

SDL_PollEvent(&event);

if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
{
    // Move centerpoint of rotation for one of the trees:
    if (keyboard_state_array[SDL_SCANCODE_UP] && !(keyboard_state_array[SDL_SCANCODE_DOWN]))
    {
        --location.y;
    }
    else if (!keyboard_state_array[SDL_SCANCODE_UP] && keyboard_state_array[SDL_SCANCODE_DOWN])
    {
        ++location.y;
    }

    if (keyboard_state_array[SDL_SCANCODE_RIGHT] && !keyboard_state_array[SDL_SCANCODE_LEFT])
    {
        ++location.x;
    }
    else if (!keyboard_state_array[SDL_SCANCODE_RIGHT] && keyboard_state_array[SDL_SCANCODE_LEFT])
    {
        --location.x;
    }
}

这真是一个很好的解决方案,几乎可以在你的所有游戏中使用。除了
其他ifs
&&s
,我们可以只放ifs,一切都一样,不需要附加条件。
class KeyboardHandler {
    handleKeyboardEvent(SDL Event) {
        keyState[event.code] = event.state;
    }

    bool isPressed(keyCode) {
        return (keyState[keyCode] == PRESSED);
    }

    bool isReleased(keyCode) {
        return (keyState[keyCode] == RELEASED);
    }

    keyState[];
}

...

while(SDL Pull events)
{
    switch(event.type) {
        case SDL_KEYDOWN:
        case SDL_KEYUP:
                keyHandler.handleKeyboardEvent(event);
            break;
        case SDL_ANOTHER_EVENT:
                ...
            break;
    }   
}

// When you need to use it:
if(keyHandler.isPressed(SOME_KEY) && keyHandler.isPressed(SOME_OTHER_KEY))
    doStuff(TM);
const Uint8 *keyboard_state_array = SDL_GetKeyboardState(NULL);

SDL_PollEvent(&event);

if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
{
    // Move centerpoint of rotation for one of the trees:
    if (keyboard_state_array[SDL_SCANCODE_UP] && !(keyboard_state_array[SDL_SCANCODE_DOWN]))
    {
        --location.y;
    }
    else if (!keyboard_state_array[SDL_SCANCODE_UP] && keyboard_state_array[SDL_SCANCODE_DOWN])
    {
        ++location.y;
    }

    if (keyboard_state_array[SDL_SCANCODE_RIGHT] && !keyboard_state_array[SDL_SCANCODE_LEFT])
    {
        ++location.x;
    }
    else if (!keyboard_state_array[SDL_SCANCODE_RIGHT] && keyboard_state_array[SDL_SCANCODE_LEFT])
    {
        --location.x;
    }
}