【问题标题】:How do I enable SDL2 to allow all key_down events and not just the quit event?如何启用 SDL2 以允许所有 key_down 事件而不仅仅是退出事件?
【发布时间】:2018-08-31 16:07:58
【问题描述】:

我的 SDL 窗口在另一个位图之上显示位图,但是我无法使用 SDL_KeyDown 事件控制位图图像。唯一有效的事件是 SDL_QUIT。

我尝试使用 ASWD 键和上下左右箭头键进行映射,但是 SDL 窗口不处理任何这些事件。唯一发生的事件是当我单击 X 按钮关闭窗口或按 q 或退出键关闭窗口时。此外,控制台上没有出现任何 printf 语句,所以我不确定问题出在哪里,因为程序编译并运行时没有任何错误。

我使用的是 C 而不是 C++

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_timer.h>
#include <SDL_image.h>


#define WINDOW_WIDTH (640)
#define WINDOW_HEIGHT (480)
// Speed in Pixels/Seconds
#define SCROLL_SPEED (300)

// Spirte Size
#define SPRITE_SIZE    32


int main(int argc, const char * argv[]) {

// Attempt to initialize graphics library
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
    SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
    return 1;
}

//Initialize Key Variables
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Surface *windowSurface = NULL;
SDL_Surface *imageSurface = NULL;



// Creating Surfaces and Addresses
SDL_Surface *temp = NULL;
SDL_Surface *sprite = NULL;

// set sprite position
SDL_Rect dstSprite = {0, 0, 32, 32};


// Attempt to create SDL Window
window = SDL_CreateWindow("Atari Lunar Lander", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, 0);

// Print an Error if the window fails to initialize
if (window == NULL) {
    printf("Could not create window: %s\n", SDL_GetError());
    return 1;
}

// Create The Title of the Window
SDL_SetWindowTitle(window, "Atari Lunar Lander");

// Create SDL Render Window
Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE;
renderer = SDL_CreateRenderer(window, -1, render_flags);

// if rendering the window fails
if (!renderer) {
    printf("error creating render: %s\n", SDL_GetError());
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 1;
}

windowSurface = SDL_GetWindowSurface(window);

// Load A bitmap image as an Surface
windowSurface = SDL_LoadBMP("/Users/jeremiahonwubuya/Desktop/AtariLunarLander/outerspace.bmp");

if (!windowSurface) {
    printf("error creating surface: %s\n", SDL_GetError());
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 1;
}

//Load Image data into graphics hardware memory
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, windowSurface);


if (!texture) {
    printf("error creating texture: %s\n", SDL_GetError());
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 1;
}


// load bitmap image into an SDL_Surface "temp" and store "temp" into the SDL_Surface "sprite" that is optimized for Blitting
temp   = SDL_LoadBMP("/Users/jeremiahonwubuya/Desktop/AtariLunarLander/player.bmp");
sprite = SDL_ConvertSurface(temp, temp->format, 0);
SDL_FreeSurface(temp);

SDL_Texture *playerTexture = SDL_CreateTextureFromSurface(renderer, sprite);


if (!sprite) {
    printf("error creating sprite: %s\n", SDL_GetError());
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 1;
}



// updating the Window Surface to be the BitMap Image
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderCopy(renderer, playerTexture, NULL, &dstSprite);
SDL_RenderPresent(renderer);



bool isRunning = true;
SDL_Event event;

while (isRunning) {

    while (SDL_PollEvent(&event) != 0 ) {
        if (event.type == SDL_QUIT) {
            // close button clicked
            isRunning = false;
            break;
        }

        if (event.type == SDL_KEYDOWN) {
            // close program upon buttons pressed
            switch(event.key.keysym.sym){
                case SDLK_q:
                    printf("program stopped");
                    isRunning = false;
                    break;
                case SDLK_ESCAPE:
                    printf("programm stopped");
                    isRunning = false;
                    break;

            }

            // Animating the Sprite

            if (event.key.keysym.sym == SDLK_a || event.key.keysym.sym == SDLK_LEFT) {
                dstSprite.x -= 5;
                dstSprite.w = 32;
                dstSprite.h = 32;
                SDL_RenderClear(renderer);
                SDL_RenderCopy(renderer, texture, NULL, NULL);
                SDL_RenderCopy(renderer, playerTexture, NULL, &dstSprite);
                SDL_RenderPresent(renderer);
                printf("sprite moved leftt to position %d \n", dstSprite.x);

     }

            if (event.key.keysym.sym == SDLK_d || event.key.keysym.sym == SDLK_RIGHT) {
                dstSprite.x += 5;
                dstSprite.w = 32;
                dstSprite.h = 32;
                SDL_RenderClear(renderer);
                SDL_RenderCopy(renderer, texture, NULL, NULL);
                SDL_RenderCopy(renderer, playerTexture, NULL, &dstSprite);
                SDL_RenderPresent(renderer);
                printf("sprite moved right to position %d \n", dstSprite.x);

            }

            if (event.key.keysym.sym == SDLK_w || event.key.keysym.sym == SDLK_UP) {
                dstSprite.y -= 5;
                dstSprite.w = 32;
                dstSprite.h = 32;
                SDL_RenderClear(renderer);
                SDL_RenderCopy(renderer, texture, NULL, NULL);
                SDL_RenderCopy(renderer, playerTexture, NULL, &dstSprite);
                SDL_RenderPresent(renderer);
                printf("sprite moved up to position %d \n", dstSprite.y);


            }

            if (event.key.keysym.sym == SDLK_s || event.key.keysym.sym == SDLK_DOWN) {
                dstSprite.y += 5;
                dstSprite.w = 32;
                dstSprite.h = 32;
                SDL_RenderClear(renderer);
                SDL_RenderCopy(renderer, texture, NULL, NULL);
                SDL_RenderCopy(renderer, playerTexture, NULL, &dstSprite);
                SDL_RenderPresent(renderer);
                printf("sprite moved down to position %d \n", dstSprite.y);


            }

        }


      // Prevent Sprite from colliding with the edges of the screen

        if ( dstSprite.x < 0 ) {
            dstSprite.x = 0;
        }
        else if ( dstSprite.x > WINDOW_WIDTH-SPRITE_SIZE ) {
            dstSprite.x = WINDOW_WIDTH-SPRITE_SIZE;
        }
        if ( dstSprite.y < 0 ) {
            dstSprite.y = 0;
        }
        else if ( dstSprite.y > WINDOW_HEIGHT-SPRITE_SIZE ) {
            dstSprite.y = WINDOW_HEIGHT-SPRITE_SIZE;
        }


        // Draw the Sprite
        SDL_BlitSurface(sprite, NULL, windowSurface, &dstSprite);


        SDL_UpdateWindowSurface(window);
    }

}


SDL_Delay(5000);

// Clean Up

// Free SDL Surfaces
SDL_FreeSurface(sprite);
sprite = NULL;
SDL_FreeSurface(windowSurface);
windowSurface = NULL;
SDL_FreeSurface(imageSurface);
imageSurface = NULL;
// Destroy Texture and Window
texture = NULL;
SDL_DestroyTexture(texture);
playerTexture = NULL;
SDL_DestroyTexture(playerTexture);
window = NULL;
SDL_DestroyWindow(window);
SDL_Quit();

}

【问题讨论】:

    标签: c sdl-2 xcode9


    【解决方案1】:

    您对您的案例进行 OR 运算,从而产生与 .sym 中不同的整数。您应该拆分 OR,让它们通过或使用 if 条件。例如:

    case SDLK_a:    
    case SDLK_LEFT: 
       printf("sprite moved leftt");
       break;
    
    case SDLK_d:
    case SDLK_RIGHT:
      printf("sprite moved right");
      break;
    
    case SDLK_w:
    case SDLK_UP:
      printf("sprite moved up");
      break;
    
    case SDLK_s:
    case SDLK_DOWN:
      printf("sprite moved down");
      break;
    

    或者

    if (event.key.keysym.sym == SDLK_a || event.key.keysym.sym == SDLK_LEFT)
      // do something..
    

    所以有几件事,首先你的代码是“工作”,当我按下正确的键时我会打印出文本但你有另一个错误,ifs 中的那些中断让你跳过 bliting 部分,记住中断在 switch、for 和 while 循环中中断执行流程,您不需要在 ifs 上使用它们。

    此外,如果您按下一个键然后不按任何键,您应该会更新您的屏幕。我用这个程序进行了测试。告诉我它是否正在接收你的钥匙..

    #include <SDL2/SDL.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
        SDL_Init(SDL_INIT_VIDEO);
    
        bool isRunning = true;
        SDL_Event event;
        SDL_Rect dstSprite = {0, 0, 0, 0};
        while (isRunning) {
    
            while (SDL_PollEvent(&event) != 0) {
                if (event.type == SDL_QUIT) {
                    // close button clicked
                    isRunning = false;
                    break;
                }
    
                if (event.type == SDL_KEYDOWN) {
                    // close program upon buttons pressed
                    switch (event.key.keysym.sym) {
                    case SDLK_q:
                        printf("program stopped");
                        isRunning = false;
                        break;
                    case SDLK_ESCAPE:
                        printf("programm stopped");
                        isRunning = false;
                        break;
                    }
    
                    // Animating the Sprite
    
                    if (event.key.keysym.sym == SDLK_a ||
                        event.key.keysym.sym == SDLK_LEFT) {
                        dstSprite.x -= 5;
                        printf("sprite moved leftt to position %d \n", dstSprite.x);
                        break;
                    }
    
                    if (event.key.keysym.sym == SDLK_d ||
                        event.key.keysym.sym == SDLK_RIGHT) {
                        dstSprite.x += 5;
                        printf("sprite moved right to position %d \n", dstSprite.x);
                        break;
                    }
    
                    if (event.key.keysym.sym == SDLK_w ||
                        event.key.keysym.sym == SDLK_UP) {
                        dstSprite.y -= 5;
                        printf("sprite moved up to position %d \n", dstSprite.y);
                        break;
                    }
    
                    if (event.key.keysym.sym == SDLK_s ||
                        event.key.keysym.sym == SDLK_DOWN) {
                        dstSprite.y += 5;
                        printf("sprite moved down to position %d \n", dstSprite.y);
                        break;
                    }
                }
                printf("update graphics\n");
            }
        }
    }
    

    【讨论】:

    • 我已将代码更新为“ if (event.key.keysym.sym == SDLK_a || event.key.keysym.sym == SDLK_LEFT) { dstSprite.x -= 5; printf ("sprite move leftt"); break; } " 然而精灵仍然拒绝移动。我还尝试了“ case SDLK_a: case SDLK_LEFT: dstSprite.x -= 5; printf("sprite move leftt"); break; ”,但这也不起作用。
    • @JeremiahOnwubuya 请将问题编辑为您现在拥有的内容。还可以尝试在所有按钮之后(在 blit 之前)打印 SDL_Rect 的 (x, y) 值。
    • 我已经编辑了代码并粘贴在上面。我还尝试在新窗口中移动精灵,但是精灵不只移动 q 并逃避工作。但是,没有任何内容打印到控制台,也没有错误
    • @JeremiahOnwubuya 你有 2 个纹理和一个表面。你能告诉我哪个正在调整大小吗?
    • @JeremiahOnwubuya 我还建议您对这个新问题提出一个新问题,因为这个问题已经得到解答。您遇到了一个关键问题,现在已解决(根据打印语句)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    • 2012-10-18
    • 1970-01-01
    • 2018-02-24
    相关资源
    最近更新 更多