gpt4 book ai didi

c - SDL2 : getting segmentation fault with TTF_RenderText after some time?

转载 作者:太空宇宙 更新时间:2023-11-04 07:11:50 27 4
gpt4 key购买 nike

好吧,我不确定那是为了代码审查还是为了这个网站,但它有问题,所以我想我来对地方了。我正在尝试使用 C 和 SDL 创建游戏。这是代码(下面的解释):

//Includes
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <SDL2_gfxPrimitives.h>


//Create some global variables(is there some other way to do that?)
SDL_Window *screen;
SDL_Renderer *renderer;
SDL_Texture *tardis;
SDL_Surface *tardis_surface;
SDL_Texture *gallifrey;
SDL_Surface *gallifrey_surface;
SDL_Surface *pillar_surface;
SDL_Rect tardis_dest;


//Some variables I want to keep throughout the game
float speed = 0;
int pillars = 0;
int pause = 0;


//Those two could change in the future
int WIDTH = 640;
int HEIGHT = 480;


//Define a struct to express the pillars in a better way
typedef struct{
SDL_Rect pillar_up;
SDL_Rect pillar_down;
SDL_Texture *pillar_texture;
}pillar;


//OK, that might be silly, but I create a list of pointers so
//that I can keep track of them afterwards. Is that bad?
pillar *list_dest[4];


//Generate a pillar
void create_pillar(int pillars_no, int xpos)
{
//Generate random height
int height = rand() % 200;
if(height < 50)
height += 50;
pillar pillar_dest;

//Set the coordinates for the upper pillar
pillar_dest.pillar_up.x = xpos;
pillar_dest.pillar_up.y = 0;
pillar_dest.pillar_up.w = 70;
pillar_dest.pillar_up.h = HEIGHT - (height + 180);

//Set the coordinates for the pillar on the ground
pillar_dest.pillar_down.x = xpos;
pillar_dest.pillar_down.y = HEIGHT - height;
pillar_dest.pillar_down.w = 70;
pillar_dest.pillar_down.h = 200;

//Set the pillar texture
pillar_dest.pillar_texture = SDL_CreateTextureFromSurface(
renderer, pillar_surface);

//Allocate space for the pillar and save the address
//in the list_dest
pillar *pillar_destp = malloc(sizeof(pillar_dest));
*pillar_destp = pillar_dest;
list_dest[pillars_no % 3] = pillar_destp;
}


//Check if the Tardis collides with a pillar
int check_collision(SDL_Rect A, SDL_Rect B)
{
//The sides of the rectangles
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;

//Calculate the sides of rect A
leftA = A.x;
rightA = A.x + A.w;
topA = A.y;
bottomA = A.y + A.h;

//Calculate the sides of rect B
leftB = B.x;
rightB = B.x + B.w;
topB = B.y;
bottomB = B.y + B.h;

//If any of the sides from A are outside of B
if(bottomA < topB)
{
return 0;
}

if(topA > bottomB)
{
return 0;
}
if(rightA < leftB)
{
return 0;
}
if(leftA > rightB)
{
return 0;
}
//Else
return 1;
}


//Render the pillars(shitty function name, whatever...)
void draw_ground()
{
//I always create 3 pillars, no more
if(pillars < 3)
{
create_pillar(pillars, WIDTH + pillars * 240);
pillars += 1;
}
else
{
int i;
for(i = 0; i < 3; i++)
{
//Free the previous pillars
pillar *current_pillar;
current_pillar = list_dest[i];
if(current_pillar->pillar_up.x < -70)
{
free(current_pillar->pillar_texture);
free(current_pillar);
create_pillar(pillars, WIDTH);
pillars += 1;
}
else
{
//Check if the Tardis has collided with a pillar and
//display a "game over" message.
if(check_collision(current_pillar->pillar_up, tardis_dest) ||
check_collision(current_pillar->pillar_down, tardis_dest))
{
SDL_Rect target;
target.x = (WIDTH / 2) - 100;
target.y = (HEIGHT / 2) - 50;
target.w = 200;
target.h = 100;
TTF_Font *font;
font = TTF_OpenFont("DALEK.ttf", 40);
SDL_Surface *text;
SDL_Color text_color = {255, 255, 0};
text = TTF_RenderText_Solid(font,
"GAME OVER",
text_color);
SDL_Texture *game_over;
game_over = SDL_CreateTextureFromSurface(renderer, text);
SDL_RenderCopy(renderer, game_over, NULL, &target);
pause = 1;
int j;
for(j = 0; j < 3; j++)
{
free(list_dest[j]);
}
pillars = 0;
break;

}
//Render the pillars
double angle = 180.0;
current_pillar->pillar_up.x -= 10;
current_pillar->pillar_down.x -= 10;
SDL_RenderCopyEx(renderer, current_pillar->pillar_texture,
NULL, &current_pillar->pillar_up, angle = 0.0,
NULL, SDL_FLIP_VERTICAL);
SDL_RenderCopy(renderer, current_pillar->pillar_texture,
NULL, &current_pillar->pillar_down);
}
}
}
}


//Render the pillar counter
void draw_counter()
{
SDL_Rect counter;
counter.x = WIDTH - 50;
counter.y = 10;
counter.w = 40;
counter.h = 50;

TTF_Font *font;
font = TTF_OpenFont("DALEK.ttf", 40);

SDL_Surface *count;
SDL_Color text_color = {0, 255, 255};

char count_text[3];
if(pillars >= 3)
sprintf(count_text, "%d", pillars - 3);
else
sprintf(count_text, "%d", pillars);

count = TTF_RenderText_Solid(font,
count_text,
text_color);

SDL_Texture *pillar_counter;
pillar_counter = SDL_CreateTextureFromSurface(renderer, count);

SDL_RenderCopy(renderer, pillar_counter, NULL, &counter);
//This is the last function of the game loop, so I suppose it's a good
//place for the SDL_RenderPresent
SDL_RenderPresent(renderer);
}


//Load the images used in the game
void load_images()
{
tardis_surface = IMG_Load("files/tardis.bmp");
gallifrey_surface = IMG_Load("files/gallifrey.bmp");
pillar_surface = IMG_Load("files/pipe.bmp");
}


//Create the background and the Tardis in it's initial place
void create_sprites()
{
//Create area for the TARDIS
tardis_dest.x=50;
tardis_dest.y=100;
tardis_dest.w=50;
tardis_dest.h=80;

//Color key the TARDIS and create texture
Uint32 colorkey = SDL_MapRGB(tardis_surface->format,0,0,0);
//SDL_DisplayFormat(tardis_surface);
SDL_SetColorKey(tardis_surface, SDL_SRCCOLORKEY, colorkey); // That doesn't work!!!!!
//Why? Any ideas?

tardis = SDL_CreateTextureFromSurface(renderer, tardis_surface);

//Create texture for the Gallifreyan background
gallifrey = SDL_CreateTextureFromSurface(renderer, gallifrey_surface);

//Clear the renderer
SDL_RenderClear(renderer);

//Add textures to renderer
SDL_RenderCopy(renderer, gallifrey, NULL, NULL);
SDL_RenderCopy(renderer, tardis, NULL, &tardis_dest);

//Update renderer
//SDL_RenderPresent(renderer);
}


//Update the Tardis' position
void update_sprites(float time)
{
speed += time * 28;
if(tardis_dest.y > 460)
{
tardis_dest.y = 460;
speed = 0;
}
else if(tardis_dest.y < 0)
{
tardis_dest.y = 0;
speed = 0;
}
else
{
tardis_dest.y += speed;
SDL_RenderCopy(renderer, gallifrey, NULL, NULL);
SDL_RenderCopy(renderer, tardis, NULL, &tardis_dest);
//SDL_RenderPresent(renderer);
}
}


//Change the speed when clicked
void ignite()
{
if(speed > 0)
speed = -10;
else
speed -= 10;
}


//The main function
int main(int argc, char *argv[])
{

SDL_Event ev;
int active = 1;

if(SDL_Init(SDL_INIT_EVERYTHING) != 0)
fprintf(stderr, "Could not initialize SDL. SDL Error: %s\n", SDL_GetError());
else
printf("SDL initialized.\n");

if(TTF_Init() == 0)
fprintf(stderr, "TTF initialized.\n");
else
fprintf(stderr, "Could not initialize TTF.\n");

//Open main window
screen = SDL_CreateWindow
(
"First Game", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
WIDTH,
HEIGHT,
SDL_WINDOW_SHOWN
);

if(!screen)
fprintf(stderr, "Could not set video mode: SDL Error: %s\n", SDL_GetError());

renderer = SDL_CreateRenderer(screen, 0, SDL_RENDERER_ACCELERATED);

//Draw the environment
load_images();
create_sprites();

//Set time
Uint32 current_time, old_time;
float time_passed;
current_time = SDL_GetTicks();

while(active)
{
//Update time
old_time = current_time;
current_time = SDL_GetTicks();
time_passed = (current_time - old_time) / 1000.0f;

//Handle Events
while(SDL_PollEvent(&ev))
{

if(ev.type == SDL_QUIT)
active = 0;
if(ev.type == SDL_MOUSEBUTTONDOWN)
{
if(pause)
{
pause = 0;
}
else
ignite();
}
}
if(pause)
continue;
update_sprites(time_passed);
draw_ground();
draw_counter();
SDL_Delay(40);
}

//Exit
SDL_FreeSurface(tardis_surface);
SDL_FreeSurface(gallifrey_surface);
SDL_Quit();
printf("SDL terminated. Have a nice day...\n");
return 0;
}

读起来不错吧?它可能有很多缺陷,因为这是我第一次尝试游戏编程,但我的主要问题是玩了一段时间后我遇到了段错误。使用 gdb,我发现是以下命令导致了问题:

count = TTF_RenderText_Solid(font,
count_text,
text_color);

位于 draw_counter() 函数的第 214 行(中间某处)。问题是:为什么?我想这与我正在做的内存分配有关(我还在学习 C,这是一个非常棘手的部分,来自 Python)。如果有人可以提供一些有用的信息?谢谢顺便说一句,请不要用通常的“不要使用 C,学习 C++ 或 Java”甚至“只使用 Unity”来回应,我想学习 C,并可能在此过程中学习一些游戏编程。

最佳答案

肯定是不断调用font = TTF_OpenFont("DALEK.ttf", 40);,过了一段时间就失败了。

SDL 为每个打开的字体分配内存,有时您会用完。 (也许文件保持打开状态并且您的系统用完了文件句柄。)您需要关闭字体句柄:添加

TTF_CloseFont( font );

在打开它的例程结束时。或者,只打开字体一次(在您的 main 中)例程并将它们的句柄保存在全局变量中。

顺便说一句,我还注意到你对表面的处理也很自由。使用类似的函数 SDL_FreeSurface 当你完成一个时,再次防止只使用一次资源但仍然分配它们。 (这是针对 SDL 1.0 的,我已经习惯了。查看 SDL 2 文档。)

关于c - SDL2 : getting segmentation fault with TTF_RenderText after some time?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27785880/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com