简体   繁体   中英

How do I enable SDL2 to allow all key_down events and not just the quit event?

My SDL Window displays a bitmap on top of another bitmap however I am not able to control the bitmap image using SDL_KeyDown events. The only event that works is SDL_QUIT.

I attempted to map using the ASWD keys and the Up Down Left and Right arrow keys, however the SDL Window doesn't process any of those events. The only event that occurs is when I click the X button to close the window or when I press the q or escape keys to close the window. Also, none of the printf statements are appearing on the console so I am not sure exactly where the problem is because the program compiles and runs without any errors.

I am using C not 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();

}

Your OR'ing your cases thus producing different integers than what are in .sym. You should split your ORs and let them fallthrough or use an if condition. For example:

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;

Or

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

So a few things, first your code is "working", I get printed the text out when I press the correct keys but you have another error, those breaks in the ifs are making you skip the bliting section, remember that breaks break the execution flow in switch, for, and while loops, you don't need them on ifs.

Also If you press a key and then don't press anything you should be getting your screen updated. I tested with this program. Tell me if it is receiving your keys..

#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");
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM