如何启用 SDL2 以允许所有 key_down 事件而不仅仅是退出事件?
How do I enable SDL2 to allow all key_down events and not just the quit event?
我的 SDL Window 在另一个位图之上显示一个位图,但是我无法使用 SDL_KeyDown 事件控制位图图像。唯一有效的事件是 SDL_QUIT.
我尝试使用 ASWD 键和上下左右箭头键进行映射,但是 SDL Window 不处理任何这些事件。唯一发生的事件是当我单击 X 按钮关闭 window 或当我按 q 或转义键关闭 window 时。此外,none 的 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();
}
您对您的案例进行 OR'ing,从而产生与 .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..
所以有几件事,首先你的代码是 "working",当我按下正确的键时我打印了文本但是你有另一个错误,ifs 中的那些中断让你跳过了 bliting 部分, 请记住 break 会中断 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");
}
}
}
我的 SDL Window 在另一个位图之上显示一个位图,但是我无法使用 SDL_KeyDown 事件控制位图图像。唯一有效的事件是 SDL_QUIT.
我尝试使用 ASWD 键和上下左右箭头键进行映射,但是 SDL Window 不处理任何这些事件。唯一发生的事件是当我单击 X 按钮关闭 window 或当我按 q 或转义键关闭 window 时。此外,none 的 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();
}
您对您的案例进行 OR'ing,从而产生与 .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..
所以有几件事,首先你的代码是 "working",当我按下正确的键时我打印了文本但是你有另一个错误,ifs 中的那些中断让你跳过了 bliting 部分, 请记住 break 会中断 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");
}
}
}