简体   繁体   English

如何在 sdl2 上按下键盘时更改图像

[英]how to change the image when pressing the keyboard on sdl2

I have been working on this game using SDL2.0 and C and hit a snag.我一直在使用 SDL2.0 和 C 开发这款游戏,但遇到了麻烦。 As title say, I want to make image change when users press the keyboard, but it doesn't work.So I want to konw where the code is wrong.正如标题所说,我想在用户按下键盘时更改图像,但它不起作用。所以我想知道代码错在哪里。

Here is the code.这是代码。

#include <stdio.h>
#include <sdl2/SDL.h>
#include <sdl2/SDL_image.h>


int main(int argc, char* args[]){
    bool quit = false;
    SDL_Event event;
 
    SDL_Init(SDL_INIT_VIDEO);
 
    SDL_Window * window = SDL_CreateWindow("SDL2 Displaying Image",
    SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Surface * image = SDL_LoadBMP("opening_ps1.bmp");     
    SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, image);
 
    while (!quit){
        SDL_WaitEvent(&event);
        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);
        
        while(SDL_PollEvent(&event)){
            if(event.type == SDL_QUIT){
                quit = true;
                break;
            }
            
            if(event.type == SDL_KEYDOWN){
                switch(event.key.keysym.sym){
                    case SDL_SCANCODE_A:
                        quit = false;
                        SDL_Renderer * renderer1 = SDL_CreateRenderer(window, -1, 0);
                        SDL_Surface * image1 = SDL_LoadBMP("opening_2.bmp");     
                        SDL_Texture * texture1 = SDL_CreateTextureFromSurface(renderer1, image1);
                        SDL_RenderClear(renderer);
                        SDL_RenderCopy(renderer1, texture1, NULL, NULL);
                        SDL_RenderPresent(renderer1);
                        break;
                }
            }
        }
    }

    SDL_FreeSurface(image);    
    SDL_DestroyWindow(window);

    SDL_Quit();
 
    return 0;
    }
    

Here is your code working perfectly, let me explain how it works, Please don't forget to change the file names, I have used pngs.这是您的代码完美运行,让我解释一下它是如何工作的,请不要忘记更改文件名,我使用了 png。 but you can do the same thing with bmps.但是你可以用 bmps 做同样的事情。

SDL_image.h SDL_image.h

First of all I have assumed that you might want to load other types of files than only bmps, and since you had that library in import I thought I can include that in the code!首先,我假设您可能想要加载其他类型的文件,而不仅仅是 bmps,并且由于您在导入中有该库,我认为我可以将其包含在代码中!

The main loop主循环

You had a double loop which is something you don't really need here, we can just have an infinite loop and the break condition inside.你有一个双循环,这是你在这里并不真正需要的东西,我们可以有一个无限循环和里面的中断条件。

The SDL_FreeSurface SDL_FreeSurface

Since after the textures have been created we no longer need surface, we can free them immediately因为在创建纹理后我们不再需要表面,我们可以立即释放它们

SDL_SCANCODE_A SDL_SCANCODE_A

This is what you were comparing the result of event.key.keysym.sym to, however the type of event.key.keysym.sym is SDL_Keycode so you had to compare it to SDLK_a in order to trigger the change of the image when the key a is pressed这就是您将event.key.keysym.sym event.key.keysym.sym类型是SDL_Keycode ,因此您必须将其与SDLK_a进行比较,以便在键 a 被按下

    #include <SDL2/SDL.h>
    #include <SDL2/SDL_image.h>
    #include <stdbool.h>
    
    int main(int argc, char *args[])
    {
        SDL_Event event;
    
        SDL_Init(SDL_INIT_VIDEO);
        IMG_Init(IMG_INIT_PNG);
    
        SDL_Window *window = SDL_CreateWindow("SDL2 Displaying Image",
                                              SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
        SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
        SDL_Surface *image = IMG_Load("akward.png");
        SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, image);
        SDL_FreeSurface(image);
        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);
    
        while (1)
        {
            SDL_PollEvent(&event);
            if (event.type == SDL_QUIT)
            {
                break;
            }
    
            if (event.type == SDL_KEYDOWN)
            {
                switch (event.key.keysym.sym)
                {
                case SDLK_a:
                    SDL_Surface *image1 = IMG_Load("output.png");
                    SDL_Texture *texture1 = SDL_CreateTextureFromSurface(renderer, image1);
                    SDL_FreeSurface(image1);
                    SDL_RenderClear(renderer);
                    SDL_RenderCopy(renderer, texture1, NULL, NULL);
                    SDL_RenderPresent(renderer);
                    break;
                }
            }
        }
        
        SDL_DestroyWindow(window);
    
        SDL_Quit();
    
        return 0;
    }

EDIT:编辑:

Here is the code that will allow you to take all images from a directory and show them.这是允许您从目录中获取所有图像并显示它们的代码。 I will do a brief explanation if you are interested, First of all I have written a macro that will allow you to specify the number of images in a directory, please make sure it is the correct number!如果您有兴趣,我会做一个简短的解释,首先我写了一个宏,允许您指定目录中的图像数量,请确保它是正确的数量! I have put 5 for testing purposes!我已经放了 5 个用于测试目的! #define IMG_NUMBER 5

I have created two more functions, the my_str_concat is just to concatenate the directory name and the file name so it can be opened by IMG_Load .我又创建了两个函数, my_str_concat只是连接目录名和文件名,以便它可以被IMG_Load打开。 The create_texture_array creates an array of textures so that they can be used by the main function afterwards create_texture_array创建一个纹理数组,以便之后的主 function 可以使用它们

    #include <SDL2/SDL.h>
    #include <SDL2/SDL_image.h>
    #include <stdbool.h>
    #include <dirent.h>
    #include <errno.h>
    
    #define IMG_NUMBER 5
    
    char * my_str_concat(const char * input_directory, char * file_name)
    {
        size_t input_directory_size = strlen(input_directory);
        //The + 257 is for the max size of file_name
        char * res = malloc(sizeof(char)*(input_directory_size+257));
        strcpy(res,input_directory);
        strcat(res,file_name);
        return res;
    }
    
    SDL_Texture ** create_texture_array(const char * input_directory,SDL_Renderer *renderer)
    {
        SDL_Texture ** texture_array = malloc(sizeof(SDL_Texture *) * IMG_NUMBER);
        int i = 0;
        DIR *images_dir;
    
        if (NULL == (images_dir = opendir(input_directory)))
        {
            fprintf(stderr, "Error : Failed to open input directory - %s\n", strerror(errno));
            return NULL;
        }
        struct dirent * image_file;
        while((image_file = readdir(images_dir)))
        {
            //We don't want to read current and parent directories!
            if (!strcmp (image_file->d_name, "."))
            {
                continue;
            }
            if (!strcmp (image_file->d_name, ".."))
            {
                continue;
            }
    
            char * relative_file_path = my_str_concat(input_directory,image_file->d_name);
            printf("%s\n",relative_file_path);
            SDL_Surface *image = IMG_Load(relative_file_path);
            free(relative_file_path);
            SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, image);
            SDL_FreeSurface(image);
            texture_array[i] = texture;
            i++;
        }
        return texture_array;
    }
    
    void free_array(SDL_Texture ** arr, size_t size)
    {
        for (size_t i = 0; i < size; i++)
        {
            SDL_DestroyTexture(arr[i]);
        }
    }
    
    int main(int argc, char *args[])
    {
        SDL_Event event;
    
        int i = 0;
    
        SDL_Init(SDL_INIT_VIDEO);
        IMG_Init(IMG_INIT_PNG);
    
    
        SDL_Window *window = SDL_CreateWindow("SDL2 Displaying Image",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
    
        SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
    
        SDL_Texture ** texture_array = create_texture_array("img/",renderer);
    
        SDL_RenderCopy(renderer, texture_array[0], NULL, NULL);
        SDL_RenderPresent(renderer);
    
    
        while (1)
        {
            SDL_PollEvent(&event);
            if (event.type == SDL_QUIT)
            {
                break;
            }
    
            if (event.type == SDL_KEYDOWN && i+1 < IMG_NUMBER)
            {
                switch (event.key.keysym.sym)
                {
                case SDLK_a:
                    i++;
                    SDL_RenderClear(renderer);
                    SDL_RenderCopy(renderer, texture_array[i], NULL, NULL);
                    SDL_RenderPresent(renderer);
                    break;
                }
            }
        }
    
        free_array(texture_array,IMG_NUMBER);
        SDL_DestroyWindow(window);
    
        SDL_Quit();
    
        return 0;
    }

I hope this will be helpful, If this does answer your question please don't hesitate to mark this answer as correct!我希望这会有所帮助,如果这确实回答了您的问题,请不要犹豫,将此答案标记为正确! Best regards,最好的祝福,

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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