如何在 sdl2 上按下键盘时更改图像
how to change the image when pressing the keyboard on sdl2
我一直在使用 SDL2.0 和 C 开发这款游戏,但遇到了麻烦。正如标题所说,我想在用户按下键盘时更改图像,但它不会work.So我想知道代码哪里错了。
这是代码。
#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;
}
这是你的代码完美运行,让我解释一下它是如何工作的!
请不要忘记更改文件名,我用的是 png,但你可以用 bmps 做同样的事情。
SDL_image.h
首先,我假设您可能想要加载其他类型的文件,而不仅仅是 bmps,并且由于您在导入中有该库,我认为我可以将其包含在代码中!
主循环
你有一个双循环,这是你在这里并不真正需要的东西,我们可以有一个无限循环和里面的中断条件。
SDL_FreeSurface
由于创建纹理后我们不再需要表面,我们可以立即释放它们
SDL_SCANCODE_A
这是您将 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;
}
编辑:
这是允许您从目录中获取所有图像并显示它们的代码!如果您有兴趣,我会做一个简短的解释。首先,我写了一个宏,允许您指定目录中的图像数量,请确保它是正确的数量!我已经放了 5 个用于测试目的!
#define IMG_NUMBER 5
我又创建了两个函数,my_str_concat只是为了连接目录名和文件名,所以可以用IMG_Load
打开. create_texture_array
创建一个纹理数组,以便之后的主函数可以使用它们
#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;
}
希望对您有所帮助!如果这确实回答了您的问题,请不要犹豫将此答案标记为正确!
最好的问候,
我一直在使用 SDL2.0 和 C 开发这款游戏,但遇到了麻烦。正如标题所说,我想在用户按下键盘时更改图像,但它不会work.So我想知道代码哪里错了。
这是代码。
#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;
}
这是你的代码完美运行,让我解释一下它是如何工作的! 请不要忘记更改文件名,我用的是 png,但你可以用 bmps 做同样的事情。
SDL_image.h
首先,我假设您可能想要加载其他类型的文件,而不仅仅是 bmps,并且由于您在导入中有该库,我认为我可以将其包含在代码中!
主循环
你有一个双循环,这是你在这里并不真正需要的东西,我们可以有一个无限循环和里面的中断条件。
SDL_FreeSurface
由于创建纹理后我们不再需要表面,我们可以立即释放它们
SDL_SCANCODE_A
这是您将 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;
}
编辑:
这是允许您从目录中获取所有图像并显示它们的代码!如果您有兴趣,我会做一个简短的解释。首先,我写了一个宏,允许您指定目录中的图像数量,请确保它是正确的数量!我已经放了 5 个用于测试目的!
#define IMG_NUMBER 5
我又创建了两个函数,my_str_concat只是为了连接目录名和文件名,所以可以用IMG_Load
打开. create_texture_array
创建一个纹理数组,以便之后的主函数可以使用它们
#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;
}
希望对您有所帮助!如果这确实回答了您的问题,请不要犹豫将此答案标记为正确! 最好的问候,