SDL编程入门(18)按键状态

按键状态

正如我们在鼠标输入教程中看到的那样,除了使用事件之外,还有其他方法可以获得输入设备(鼠标、键盘等)的状态。在本教程中,我们将使用按键状态而不是事件来重新制作键盘输入教程

//Main loop flag
bool quit = false;

//Event handler
SDL_Event e;

//Current rendered texture
LTexture* currentTexture = NULL;

在进入主循环之前,我们声明一个纹理指针来跟踪我们要渲染到屏幕上的纹理。

//While application is running
while( !quit )
{
    //Handle events on queue
    while( SDL_PollEvent( &e ) != 0 )
    {
        //User requests quit
        if( e.type == SDL_QUIT )
        {
            quit = true;
        }
    }
    //根据当前的按键状态设置纹理
    const Uint8* currentKeyStates = SDL_GetKeyboardState( NULL );
    if( currentKeyStates[ SDL_SCANCODE_UP ] )
    {
        currentTexture = &gUpTexture;
    }
    else if( currentKeyStates[ SDL_SCANCODE_DOWN ] )
    {
        currentTexture = &gDownTexture;
    }
    else if( currentKeyStates[ SDL_SCANCODE_LEFT ] )
    {
        currentTexture = &gLeftTexture;
    }
    else if( currentKeyStates[ SDL_SCANCODE_RIGHT ] )
    {
        currentTexture = &gRightTexture;
    }
    else
    {
        currentTexture = &gPressTexture;
    }
    //Clear screen
    SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
    SDL_RenderClear( gRenderer );

    //Render current texture
    currentTexture->render( 0, 0 );

    //Update screen
    SDL_RenderPresent( gRenderer );
}

正如你所看到的,我们没有在事件循环中检查按键事件。我们所有的键盘输入都将通过键状态来处理。

关于SDL如何处理键状态,有一点很重要,那就是你仍然需要一个事件循环运行。SDL的内部键状态每次调用SDL_PollEvent时都会更新,所以在检查键状态之前要确保你已经轮询了队列上的所有事件。

这里我们设置了要渲染的纹理。首先,我们使用 SDL_GetKeyboardState获得一个指向按键状态数组的指针。所有键的状态都是由 SDL_Scancode 排序的。扫描码就像SDL_Keycode的值一样,只是扫描码被设计成可以和国际键盘一起使用。根据键盘布局的不同,不同的字母可能在不同的位置。扫描码是根据默认的物理按键位置,而不是它们在特定键盘上的位置。

您所要做的就是检查某个键是否被关闭,检查它在键状态数组中的状态。正如你在上面的代码中所看到的那样,如果键是按下的,我们将当前的纹理设置为相应的纹理。如果键都没有按下,我们就设置默认的纹理。

最后在这里,我们将当前纹理渲染到屏幕上。

这里下载本教程的媒体和源代码。

原文链接

关注我的公众号:编程之路从0到1
编程之路从0到1

血色v残阳 CSDN认证博客专家 编程达人
掌握C、Java、Python、Go、Dart语言等多种编程语言,擅长GUI开发,曾从事Android原生开发,Flutter跨平台开发等等工作
微信公众号:
“编程之路从0到1”
已标记关键词 清除标记
<div class="post-text" itemprop="text"> <p>I am currently learning Go and trying to make a game which allows players to press several buttons at the same time. Right now, my code works for a while, but sometimes when I randomly press, the GetKeyboardState() always records one or more keys as pressed. The weird key only can be released when I press the key again. Then everything goes correctly again. For example, I randomly press Up, Down, Left, Right, and right shift bottom on the keyboard to control the character in the game. Suddenly, the character always tries to go right and if I press Up or Down arrow, the character will just go to the top right or the bottom right. Only if I press the right arrow button again, the character can stop go right.</p> <p>I thought maybe the game goes too fast so I limit the fps under 90 but the situation still exists.</p> <p>Also, I tried to print out the keyboard status and it always shows the weird bottom was pressed when the situation happened even if I did not touch my keyboard.</p> <pre><code>func GetInput(keyState []uint8, prevKeyState []uint8) []Input { input := make([]Input, 0) if keyState[sdl.SCANCODE_UP] != 0 { input = append(input, Input{Up}) } ... // Handle Down, Right, Left if keyState[sdl.SCANCODE_RSHIFT] == 0 && prevKeyState[sdl.SCANCODE_RSHIFT] != 0 { input = append(input, Input{RShift}) } if keyState[sdl.SCANCODE_B] == 0 && prevKeyState[sdl.SCANCODE_B] != 0 { input = append(input, Input{Debug}) } // something like prevKeyState = keystate return input } </code></pre> <p>How I use it</p> <pre><code>keyState := sdl.GetKeyboardState() prevKeyState := make([]uint8, len(keyState)) for { ... input := ui.GetInput(keyState, prevKeyState) HandleInput(input, board) ... } </code></pre> </div>
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页