First I declare some global variables
TTF_Font* Pusab;
TTF_Font* HPusab;
TTF_Font* SPusab;
SDL_Surface* message;
SDL_Texture* slotOne;
SDL_Texture* slotTwo;
SDL_Texture* slotThree;
SDL_Texture* slotFour;
SDL_Texture* slotFive;
SDL_Texture* slotSix;
SDL_Texture* slotFPS;
SDL_Texture* slotfpsNum;
SDL_Texture* slotNine;
SDL_Rect rslotOne;
SDL_Rect rslotTwo;
SDL_Rect rslotThree;
SDL_Rect rslotFour;
SDL_Rect rslotFive;
SDL_Rect rslotSix;
SDL_Rect rslotFPS;
SDL_Rect rslotfpsNum;
SDL_Rect rslotNine;
I’ve created a class that makes text objects called RText
class Rtext {
private:
// Object attributes
SDL_Texture* slot; // Texture that holds the final image
SDL_Surface* message; // The surface created by the message string passed through
SDL_Rect slotRect; // Final Rectangle data
TTF_Font* font; // The font of the text
const char* messtring; // The string passed through
SDL_Color color; // The color of the text
int x; // The x position of the text
int y; // The y position of the text
//Creates the text using the parameters set by setText
bool create(bool wrapped, int width) {
if (wrapped == true) {
message = TTF_RenderText_Blended_Wrapped(font, messtring, color, width); // Create a wrapped text surface
if (message == NULL) {
std::cout << "Could not create message! " << SDL_GetError() << std::endl;
return false;
// code will stop running here because I used a return statement
}
slot = SDL_CreateTextureFromSurface(gRenderer, message); // Create a texture from the message surface
if (slot == NULL) {
std::cout << "Could not convert message! " << SDL_GetError() << std::endl;
return false;
// code will stop running here because I used a return statement
}
slotRect.x = x; //controls the rect's x coordinate
slotRect.y = y; // controls the rect's y coordinte
slotRect.w = message->w; // controls the width of the rect
slotRect.h = message->h; // controls the height of the rect
return true;
}
else {
message = TTF_RenderText_Blended(font, messtring, color); // Create a text surface
if (message == NULL) {
std::cout << "Could not create message! " << SDL_GetError() << std::endl;
return false;
// code will stop running here because I used a return statement
}
slot = SDL_CreateTextureFromSurface(gRenderer, message); // Create a texture from the message surface
if (slot == NULL) {
std::cout << "Could not convert message! " << SDL_GetError() << std::endl;
return false;
// code will stop running here because I used a return statement
}
slotRect.x = x; //controls the rect's x coordinate
slotRect.y = y; // controls the rect's y coordinte
slotRect.w = message->w; // controls the width of the rect
slotRect.h = message->h; // controls the height of the rect
return true;
}
}
public:
//Calls the create method and returns the finished texture
SDL_Texture* getSlot(bool wrapped, int width) {
if (create(wrapped, width)) {
return slot;
}
}
//Calls the create method and returns the finished texture's rectangle data
SDL_Rect getRect(bool wrapped, int width) {
if (create(wrapped, width)) {
return slotRect;
}
}
//Pulls in the text and sets all the text parameters
void setText(TTF_Font* f, const char* m, SDL_Color c, int _x, int _y) {
font = f;
messtring = m;
color = c;
x = _x;
y = _y;
}
};
Then I’ve made some global objects
// Create Global Text Objects
Rtext tobj1;
Rtext tobj2;
Rtext tobj3;
Rtext tobj4;
Rtext tobj5;
Rtext tobj6;
Rtext FPS;
Rtext fpsNum;
Rtext tobj9;
I have a function that loads in the assets to some global variables. Here’s a snippet of the function that shows 1 object being loaded
bool loadMenuStart() {
// Load all the text one by one
tobj1.setText(HPusab, "Nightmare at Walmart", White, 50, 50);
slotOne = tobj1.getSlot(false, NULL);
if (slotOne == NULL) {
std::cout << "Could not create Title! " << SDL_GetError() << std::endl;
return false;
// code will stop running here because I used a return statement
}
rslotOne = tobj1.getRect(false, NULL);
}
I have a similar function that loads another scene using the same object tobj1
and same global variables slotOne
and rslotOne
My problem is that when I load the other scene, the old scene’s data isn’t being deallocated. I know the code I’ve shown so far doesn’t deallocate the resources, but here’s what I’ve tried so far with deallocation.
The first thing I’ve tried is adding a function inside my RText
class called free()
that looks like this
free() {
SDL_DestroyTexture(slot);
SDL_Freesurface(message);
}
Then I call this function at the beginning of my function that loads the next scene so it looks like this
bool loadNewGame() {
tobj1.free();
// Load all the text one by one
tobj1.setText(Pusab, "I said I would never go back to Walmart,", White, 50, 50);
slotOne = tobj1.getSlot(true, 1198);
if (slotOne == NULL) {
std::cout << "Could not create Title! " << SDL_GetError() << std::endl;
return false;
// code will stop running here because I used a return statement
}
rslotOne = tobj1.getRect(true, 1198);
However, this didn’t seem to work and loading the new scene caused a memory leak. The next thing I tried was destroying the surface and textures in the create()
function instead like this
bool create(bool wrapped, int width) {
if (wrapped == true) {
message = TTF_RenderText_Blended_Wrapped(font, messtring, color, width); // Create a wrapped text surface
if (message == NULL) {
std::cout << "Could not create message! " << SDL_GetError() << std::endl;
return false;
// code will stop running here because I used a return statement
}
slot = SDL_CreateTextureFromSurface(gRenderer, message); // Create a texture from the message surface
if (slot == NULL) {
std::cout << "Could not convert message! " << SDL_GetError() << std::endl;
return false;
// code will stop running here because I used a return statement
}
slotRect.x = x; //controls the rect's x coordinate
slotRect.y = y; // controls the rect's y coordinte
slotRect.w = message->w; // controls the width of the rect
slotRect.h = message->h; // controls the height of the rect
SDL_DestroyTexture(slot);
SDL_Freesurface(message);
return true;
}
else {
message = TTF_RenderText_Blended(font, messtring, color); // Create a text surface
if (message == NULL) {
std::cout << "Could not create message! " << SDL_GetError() << std::endl;
return false;
// code will stop running here because I used a return statement
}
slot = SDL_CreateTextureFromSurface(gRenderer, message); // Create a texture from the message surface
if (slot == NULL) {
std::cout << "Could not convert message! " << SDL_GetError() << std::endl;
return false;
// code will stop running here because I used a return statement
}
slotRect.x = x; //controls the rect's x coordinate
slotRect.y = y; // controls the rect's y coordinte
slotRect.w = message->w; // controls the width of the rect
slotRect.h = message->h; // controls the height of the rect
SDL_DestroyTexture(slot);
SDL_Freesurface(message);
return true;
}
}
However this caused the rendering to stop working all together and I would just have a black screen on my window. My question is how can a properly deallocate the resources when I do a scene change? Is there a better way I can implement my text system?
Here’s the rendering function if you need it
void draw() {
if (gameState == "menu") {
SDL_RenderCopy(gRenderer, slotOne, NULL, &rslotOne);
SDL_RenderCopy(gRenderer, slotTwo, NULL, &rslotTwo);
SDL_RenderCopy(gRenderer, slotThree, NULL, &rslotThree);
SDL_RenderCopy(gRenderer, slotFour, NULL, &rslotFour);
SDL_RenderCopy(gRenderer, slotFive, NULL, &rslotFive);
SDL_RenderCopy(gRenderer, slotSix, NULL, &rslotSix);
SDL_RenderCopy(gRenderer, slotFPS, NULL, &rslotFPS);
SDL_RenderCopy(gRenderer, slotfpsNum, NULL, &rslotfpsNum);
SDL_RenderPresent(gRenderer);
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 255);
SDL_RenderClear(gRenderer);
}
else if (gameState == "newgame") {
SDL_RenderCopy(gRenderer, slotOne, NULL, &rslotOne);
SDL_RenderCopy(gRenderer, slotTwo, NULL, &rslotTwo);
SDL_RenderCopy(gRenderer, slotThree, NULL, &rslotThree);
SDL_RenderCopy(gRenderer, slotFour, NULL, &rslotFour);
SDL_RenderCopy(gRenderer, slotFive, NULL, &rslotFive);
SDL_RenderCopy(gRenderer, slotSix, NULL, &rslotSix);
SDL_RenderCopy(gRenderer, slotFPS, NULL, &rslotFPS);
SDL_RenderCopy(gRenderer, slotfpsNum, NULL, &rslotfpsNum);
SDL_RenderCopy(gRenderer, slotNine, NULL, &rslotNine);
SDL_RenderPresent(gRenderer);
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 255);
SDL_RenderClear(gRenderer);
}
else if (gameState == "ingame") {
SDL_RenderCopy(gRenderer, slotFPS, NULL, &rslotFPS);
SDL_RenderCopy(gRenderer, slotfpsNum, NULL, &rslotfpsNum);
SDL_RenderPresent(gRenderer);
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 255);
SDL_RenderClear(gRenderer);
}
}