我试着用C语言中的SDL做一个游戏界面,用户需要在文本显示后点击开始,这样它就可以把他带到菜单上。但是当文本和按钮显示时,它们消失了,留下了没有文本或按钮的空白图像,但是当我点击按钮应该在的区域时,即使它没有出现在窗口中,它也会把我带到另一个图像。
我不知道如何保持文本和按钮显示,并等待点击“开始按钮”的事件来执行我在代码中编写的操作
代码如下:
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#define SCREEN_WIDTH 1002
#define SCREEN_HEIGHT 584
#define LINE_SPACING 4
#define TEXT_COLOR {0, 0, 0, 0}
// Structure pour représenter une image
typedef struct
{
SDL_Texture* texture;
int width;
int height;
} Image;
// Fonction pour charger une image à partir d'un fichier
Image load_image(SDL_Renderer* renderer, const char* file_path)
{
SDL_Surface* surface = IMG_Load(file_path);
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
Image image;
image.texture = texture;
SDL_QueryTexture(texture, NULL, NULL, &image.width, &image.height);
return image;
}
// Fonction pour libérer la mémoire occupée par une image
void free_image(Image* image)
{
SDL_DestroyTexture(image->texture);
}
SDL_Color textColor= {255,255,255,255};
void render_text(SDL_Renderer* renderer, TTF_Font* font, const char* text, SDL_Color color, int x, int y, int delay)
{
int len = strlen(text);
char buffer[len + 1];
memset(buffer, '\0', sizeof(buffer));
int i = 0;
bool done = false;
SDL_Rect rect = { x, y, 0, 0 };
SDL_Surface* surface = NULL;
SDL_Texture* texture = NULL;
Uint32 ticks;
while (!done)
{
ticks = SDL_GetTicks();
if (i < len)
{
strncat(buffer, &text[i], 1);
surface = TTF_RenderText_Solid(font, buffer, color);
texture = SDL_CreateTextureFromSurface(renderer, surface);
rect.w = surface->w;
rect.h = surface->h;
SDL_RenderCopy(renderer, texture, NULL, &rect);
SDL_RenderPresent(renderer);
i++;
}
else
{
done = true;
}
SDL_Delay(delay - (SDL_GetTicks() - ticks));
}
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
}
void Render_text(const char* text, SDL_Rect rect)
{
SDL_Renderer* renderer = NULL;
TTF_Font* font = NULL;
SDL_Surface* surface = TTF_RenderText_Solid(font, text, textColor);
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
int tex_width, tex_height;
SDL_QueryTexture(texture, NULL, NULL, &tex_width, &tex_height);
SDL_Rect dstrect = { rect.x + rect.w / 2 - tex_width / 2, rect.y + rect.h / 2 - tex_height / 2, tex_width, tex_height };
SDL_RenderCopy(renderer, texture, NULL, &dstrect);
SDL_DestroyTexture(texture);
TTF_CloseFont(font);
}
void draw_oval(SDL_Renderer* renderer, int x, int y, int radius_x, int radius_y)
{
const int points = 100;
const float factor = 2.0f * M_PI / (float)points;
SDL_Point oval[points];
for (int i = 0; i < points; i++)
{
oval[i].x = x + (int)(radius_x * cosf(i * factor));
oval[i].y = y + (int)(radius_y * sinf(i * factor));
}
SDL_RenderDrawLines(renderer, oval, points);
}
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG);
TTF_Init();
SDL_Window* window = SDL_CreateWindow("CONNECT 4",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
TTF_Font* font1 = TTF_OpenFont("arial.ttf", 29);
TTF_Font* font2 = TTF_OpenFont("arial.ttf", 35);
TTF_Font* font = TTF_OpenFont("arial.ttf", 24);
SDL_Color color = TEXT_COLOR;
int delay = 50;
// Charger les images
Image image1 = load_image(renderer, "back.png");
Image image2 = load_image(renderer, "hand_close.png");
Image image3 = load_image(renderer, "handOpen.png");
Image image4 = load_image(renderer, "menu.png");
Image image5 = load_image(renderer, "turn.png");
Image image6 = load_image(renderer, "win.png");
// Variable pour garder une trace de l'image actuelle
Image current_image = image1;
// Effacer l'écran
SDL_RenderClear(renderer);
// Afficher l'image actuelle
SDL_RenderCopy(renderer, current_image.texture, NULL, NULL);
// Mettre à jour l'écran
SDL_RenderPresent(renderer);
//Charger image 2
SDL_Delay(500);
current_image = image2;
// Effacer l'écran
SDL_RenderClear(renderer);
// Afficher l'image actuelle
SDL_RenderCopy(renderer, current_image.texture, NULL, NULL);
// Mettre à jour l'écran
SDL_RenderPresent(renderer);
SDL_Delay(500);
//charger image 3
current_image = image3;
// Effacer l'écran
SDL_RenderClear(renderer);
// Afficher l'image actuelle
SDL_RenderCopy(renderer, current_image.texture, NULL, NULL);
// Mettre à jour l'écran
SDL_RenderPresent(renderer);
SDL_Color color1 = {255, 0, 0, 0};
render_text(renderer, font1, "You are caught in this castle!", color, 370, 300, delay);
int y_pos = 350;
render_text(renderer, font2,"To escape", color, 470, y_pos, delay);
SDL_RenderPresent(renderer);
y_pos += 50;
render_text(renderer, font1, "You need to", color, 470, y_pos, delay);
y_pos += 50;
SDL_RenderPresent(renderer);
render_text(renderer, font2,"WIN this game", color1, 430, y_pos, delay);
SDL_RenderPresent(renderer);
// Calcul de la taille du texte "START" pour le centrer dans le bouton
int oval_width = 100;
int oval_height = 50;
int oval_x = (SCREEN_WIDTH - oval_width) /2 +40;
int oval_y = SCREEN_HEIGHT - oval_height - 10; // mettre une marge de 10 pixels entre le bouton et le bord inférieur de la fenêtre
SDL_Surface* text_surface = TTF_RenderText_Solid(font, "START", textColor);
SDL_Texture* text_texture = SDL_CreateTextureFromSurface(renderer, text_surface);
SDL_Rect text_rect = { oval_x + (oval_width - text_surface->w) / 2, oval_y + (oval_height - text_surface->h) / 2, text_surface->w, text_surface->h };
// Dessin du bouton ovale
SDL_SetRenderDrawColor(renderer, 190, 140, 255, 255);
SDL_Rect oval_rect = { oval_x, oval_y, oval_width, oval_height };
SDL_RenderFillRect(renderer, &oval_rect);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderDrawRect(renderer, &oval_rect);
// Dessin du texte "START" centré dans le bouton
SDL_RenderCopy(renderer, text_texture, NULL, &text_rect);
// Affichage du rendu final
SDL_RenderPresent(renderer);
SDL_Event event;
bool done = false;
while (!done)
{
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
done=true;
break;
case SDL_MOUSEBUTTONDOWN:
// Vérification si le clic de souris est dans la zone du bouton "start"
if (event.button.x >= oval_x && event.button.x <= oval_x + oval_width && event.button.y >= oval_y && event.button.y <= oval_y + oval_height)
{
if (current_image.texture == image3.texture)
{
if (event.button.x >= 0 && event.button.x <= 1002 && event.button.y >= 0 && event.button.y <= 584)
{
current_image = image4;
printf("hhh");
}
}
else if (current_image.texture == image4.texture)
{
if (event.button.x >= 390 && event.button.x <= 610 && event.button.y >= 268 && event.button.y <= 330)
{
current_image = image5;
}
}
else if (current_image.texture == image5.texture)
{
if (event.button.x >= 0 && event.button.x <= 1002 && event.button.y >= 0 && event.button.y <= 584)
{
current_image = image6;
}
}
}
break;
default:
break;
}
}
// Effacer l'écran
SDL_RenderClear(renderer);
// Afficher l'image actuelle
SDL_RenderCopy(renderer, current_image.texture, NULL, NULL);
// Mettre à jour l'écran
SDL_RenderPresent(renderer);
}
// Libérer les ressources
free_image(&image1);
free_image(&image2);
free_image(&image3);
free_image(&image4);
free_image(&image5);
free_image(&image6);
TTF_CloseFont(font);
TTF_CloseFont(font1);
TTF_CloseFont(font2);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
TTF_Quit();
SDL_Quit();
return 0;
}
字符串
1条答案
按热度按时间zf9nrax11#
**TLDR:**开始按钮不显示,因为在
while
循环之前只渲染了一次,该循环会清除它并且不再绘制它。在你的
while
循环中,当没有事件发生时,你要做的唯一一件事是:字符串
因此,在
while
循环开始后的每一帧上,这三条指令是游戏唯一要执行的指令。以下是他们的工作:
current_image.texture
中包含的纹理在执行的这一点上,当进入循环时,
current_image.texture
包含handOpen.png
纹理。所以这是唯一能画出来的东西。即使在循环过程中引发了事件,事件处理代码所做的全部工作也只是交换要呈现的当前图像。
但在任何时候都不要再次呈现开始按钮。
在
while
循环之前**渲染了它:型
但是,由于您在
while
循环的每次迭代中都清除了窗口,并且不再绘制开始按钮,因此它不会显示。下面是
while
循环的修改版本,希望它能完成这项工作:型