首页 > 解决方案 > SDL_GetKeyboardState(NULL) 未按预期工作

问题描述

我正在用 C++/SDL2 进行乒乓克隆。要从多个键获取键盘输入,我想将 SDL_GetKeyboardState(NULL) 与 Uint8 一起使用。但是,它没有按预期工作。

预期行为:每次按键时,乒乓球拍都会上下移动。

实际行为:密钥未注册。

这是我的代码(请注意,用大写字母写的变量来自variables.h):

// g++ main.cpp `pkg-config sdl2 SDL2_ttf --cflags --libs`
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <iostream> // For io
#include <time.h>   // Rand seeder

const bool debug = true;

// Basic stuff needed for SDL2
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;

const int WINDOW_CENTER_X = WINDOW_WIDTH / 2;
const int WINDOW_CENTER_Y = WINDOW_HEIGHT / 2;

const char* WINDOW_TITLE = "Pong";

// Define the location of the paddles in the bitmap
const int PADDLE_BITMAP_X = 0;
const int PADDLE_BITMAP_Y = 0;

const int BALL_BITMAP_X = 100;
const int BALL_BITMAP_Y = 0;

// Positions of player 1 and player 2
const int PADDLE1_X = 50;
const int PADDLE2_X = WINDOW_WIDTH - 75;

// Paddle width and height
const int PADDLE_WIDTH = 20;
const int PADDLE_HEIGHT = 100;

// Speed of both players
const int PLAYER_SPEED = 0;

// Ball Speed -- this will not be constant
// The Ball Modifier will modify the speed based on the place it lands on the paddle
// Ball speed will never go under 10, and will accelerate over time
// Ball diameter
const int BALL_SPEED = 100;
const int BALL_MODIFIER = 5;
const int BALL_DIAMETER = 10;

const int BALL_CENTER_X = WINDOW_CENTER_X - BALL_DIAMETER;
const int BALL_CENTER_Y = WINDOW_CENTER_Y - BALL_DIAMETER;

const int LANG = 3;
const int LANG_ENGLISH = 3;
const int LANG_GERMAN = 4;

// Game Entity data structure
struct GameObject
{
    SDL_Rect ScreenLocation;
    SDL_Rect BitmapLocation;

    int SpeedX;
    int SpeedY;
};

// SDL stuff
SDL_Window* gWindow = NULL;
SDL_Renderer* gWindowRenderer;
SDL_Rect gScreen;
SDL_Event e;

// Game objects
GameObject gPlayer1; // Paddle 1
GameObject gPlayer2; // Paddle 2
GameObject gBall;    // Ball

// Scores. I feel like it's better to leave them uninitialized.
int gPlayer1Score;
int gPlayer2Score;

void Render();

bool init();

bool GameQuit;

void Quit();

int main( int argc, char* argv[] )
{
    // const Uint8* keyStates = SDL_GetKeyboardState(NULL);
    if( init() == false )
    {
        std::cout << "Init failed. Bye bye!\n";
        return 1;
    }
    while( !GameQuit )
    {
        const Uint8* keyStates = SDL_GetKeyboardState( NULL );
        while( SDL_PollEvent( &e ) )
        {
            if( e.type == SDL_QUIT )
                GameQuit = true;
            if( e.type == SDL_KEYDOWN )
            {
                switch( e.key.keysym.scancode )
                {
                case SDL_SCANCODE_ESCAPE:
                    GameQuit = true;
                    break;
                }
            }
        }

        if( keyStates[ SDL_SCANCODE_UP ] )
        {
            gPlayer1.ScreenLocation.y -= PLAYER_SPEED;
        }

        if( keyStates[ SDL_SCANCODE_DOWN ] )
        {
            gPlayer1.ScreenLocation.y += PLAYER_SPEED;
        }

        if( keyStates[ SDL_SCANCODE_W ] )
        {
            gPlayer2.ScreenLocation.y -= PLAYER_SPEED;
        }

        if( keyStates[ SDL_SCANCODE_S ] )
        {
            gPlayer2.ScreenLocation.y += PLAYER_SPEED;
        }

        Render();
    }
    Quit();
    return 0;
}

bool init()
{
    bool success = true;

    if( SDL_Init( SDL_INIT_VIDEO < 0 ) )
    {
        success = false;
        return success;
    }

    if( TTF_Init() < 0 )
    {
        success = false;
        return success;
    }
    srand( time( NULL ) ); // Seed rng

    // From SDL_Rect.h
    // 64 typedef struct SDL_Rect
    // 65 {
    // 66  int x, y;
    // 67  int w, h;
    // 68 } SDL_Rect;
    GameQuit = false;

    gPlayer1.ScreenLocation.y = ( ( WINDOW_HEIGHT / 2 ) - ( PADDLE_HEIGHT / 2 ) );
    gPlayer1.ScreenLocation.x = PADDLE1_X;
    gPlayer1.ScreenLocation.w = PADDLE_WIDTH;
    gPlayer1.ScreenLocation.h = PADDLE_HEIGHT;

    gPlayer2.ScreenLocation.y = ( ( WINDOW_HEIGHT / 2 ) - ( PADDLE_HEIGHT / 2 ) );
    gPlayer2.ScreenLocation.x = PADDLE2_X;
    gPlayer2.ScreenLocation.w = PADDLE_WIDTH;
    gPlayer2.ScreenLocation.h = PADDLE_HEIGHT;

    gBall.ScreenLocation.x = BALL_CENTER_X;
    gBall.ScreenLocation.y = BALL_CENTER_Y;
    gBall.ScreenLocation.w = BALL_DIAMETER;
    gBall.ScreenLocation.h = BALL_DIAMETER;

    gPlayer1.BitmapLocation.x = PADDLE_BITMAP_X;
    gPlayer1.BitmapLocation.y = PADDLE_BITMAP_Y;
    gPlayer1.BitmapLocation.w = PADDLE_WIDTH;
    gPlayer1.BitmapLocation.h = PADDLE_HEIGHT;

    gPlayer2.BitmapLocation.x = PADDLE_BITMAP_X;
    gPlayer2.BitmapLocation.y = PADDLE_BITMAP_Y;
    gPlayer2.BitmapLocation.w = PADDLE_WIDTH;
    gPlayer2.BitmapLocation.h = PADDLE_HEIGHT;

    gBall.BitmapLocation.x = BALL_BITMAP_X;
    gBall.BitmapLocation.y = BALL_BITMAP_Y;
    gBall.BitmapLocation.w = BALL_DIAMETER;
    gBall.BitmapLocation.h = BALL_DIAMETER;

    gPlayer1.SpeedY = PLAYER_SPEED;
    gPlayer1.SpeedX = 0;
    gPlayer2.SpeedY = PLAYER_SPEED;
    gPlayer2.SpeedX = 0;

    gPlayer1Score = 0;
    gPlayer2Score = 0;

    gScreen.x = 0;
    gScreen.y = 0;
    gScreen.w = WINDOW_WIDTH;
    gScreen.h = WINDOW_HEIGHT;

    // Note to self: Leave this out since color keying NULL will segfault.
    // SDL_SetColorKey(gBitmap, SDL_TRUE, SDL_MapRGB(gBitmap->format, 255, 0, 255));

    gWindow = SDL_CreateWindow(
        WINDOW_TITLE,
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        WINDOW_WIDTH,
        WINDOW_HEIGHT,
        SDL_WINDOW_MAXIMIZED );
    // Render SDL Window
    gWindowRenderer = SDL_CreateRenderer( gWindow, -1, 0 );
    if( gWindowRenderer == nullptr )
    {
        success = false;
        return success;
    }
    SDL_RenderSetLogicalSize( gWindowRenderer, WINDOW_WIDTH, WINDOW_HEIGHT );
    SDL_SetRenderDrawColor( gWindowRenderer, 0x00, 0x00, 0x00, 0xFF );

    return success;
}

// Display Menu Text
bool Menu()
{
    bool success = false;
    if( LANG == LANG_ENGLISH )
    {
        // DisplayText("Start (G)ame", 350, 250, 12, 255, 255, 255);
        // DisplayText("(Q)uit Game", 350, 270, 12, 255, 255, 255);
        success = true;
        return success;
    }

    else if( LANG == LANG_GERMAN )
    {
        // DisplayText("(G) Spielen", 350, 270, 12, 255, 255, 255);
        // DisplayText("(Q) Spiel verlassen", 350, 270, 12, 255, 255, 255);
        success = true;
        return success;
    }

    else
    {
        return success;
    }
}

void Render()
{
    SDL_RenderClear( gWindowRenderer );
    SDL_SetRenderDrawColor( gWindowRenderer, 0x00, 0x00, 0x00, 0xFF );
    SDL_RenderFillRect( gWindowRenderer, &gScreen );

    SDL_SetRenderDrawColor( gWindowRenderer, 0xFF, 0xFF, 0xFF, 0xFF );

    SDL_RenderFillRect( gWindowRenderer, &gPlayer1.ScreenLocation );

    SDL_RenderFillRect( gWindowRenderer, &gPlayer2.ScreenLocation );

    SDL_RenderFillRect( gWindowRenderer, &gBall.ScreenLocation );

    SDL_RenderPresent( gWindowRenderer );
}

void Quit()
{
    SDL_DestroyWindow( gWindow );
    SDL_Quit();
}

我不确定我做错了什么,并希望得到一个简洁的答案。感谢您的时间。

标签: c++sdl-2

解决方案


在我的 Debian 10 系统上构建和运行良好,虽然PLAYER_SPEED为零,所以if 块中的gPlayer1.ScreenLocation.y/没有任何有用的事情发生。gPlayer2.ScreenLocation.ykeyStates

设置PLAYER_SPEED为零以外的东西可以解决我的问题。


推荐阅读