# rendering numbers in SDL

This topic is 3645 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have a score int that i need to display to the screen. The only SDL function i know that displays text is TTF_RenderText_Solid() and this displays a char *. Is there a way to convert an int to a char * to display it or is there a way to render the int using an SDL function? Basically how do i display a number to the window in SDL? Thanks

##### Share on other sites
Look up string streams.

I touch on them in tutorial 12.

##### Share on other sites
You could always use a stringstream:
#include <sstream>// ...in your code...std::stringstream ss;// score is of type intss << score;// To get the char *, use// ss.str().c_str();

##### Share on other sites
ok i just use sprintf to convert it to a string and then put that string in the the function. But now i want to display a score that will update so how would i delete the old score that was displayed before i display the new score to the screen?

##### Share on other sites
ok i just use sprintf to convert it to a string and then put that string in the the function. But now i want to display a score that will update so how would i delete the old score that was displayed before i display the new score to the screen?

##### Share on other sites
Here's how I'd do it:

SDL_Surface *myScoreImage = NULL; //The image of the score to draw.int playerScore = 0; //The player's score, the one that you add/subtract to, when the player gets points.int oldPlayerScore = -1; //This one you only touch when updating 'myScoreImage'. It lets us know when we need to update.TTF_Font *myFont = NULL; //The font of the text in 'myScoreImage'.SDL_Color myTextColor = {255, 255, 255}; //The color of the text in 'myScoreImage'....//Each update frame:        //Only re-create the surface if the score has changed.    if(playerScore != oldPlayerScore)    {        //Free the old text surface.        SDL_FreeSurface(myScoreImage);                //Convert from 'int' to string here. (I usually wrap it into a function)        std::string text = "Score: " + IntToString(playerScore);                //Re-create the surface. (c_str() is the std::string function used to convert to the old 'C' style string of type char*)        //I assume you already loaded 'myFont'        myScoreImage = TTF_RenderText_Solid(myFont, text.c_str(), myTextColor);        if(myScoreImage == NULL)            printf("Error in function 'TTF_RenderText_Solid': %s\n", TTF_GetError());                //We update the 'oldPlayerScore' just so we know not to update the surface again until the score changes again.        oldPlayerScore = playerScore;    }...//Each draw frame:    SDL_Rect rect;    rect.x = 5;    rect.y = 5;        SDL_BlitSurface(myScoreImage, NULL, screen, &rect);

[Edit:] Forgot to include the 'IntToString()' function. [smile]

#include <sstream> //You'll need to include this header to use 'std::stringstream'.std::string IntToString(int n){	std::stringstream sstream;	sstream << n;	return sstream.str();}

##### Share on other sites
ok its still overwriting it. Here is what i have to display the score
I just focus on the score int.
// display the lines, level,score to the screen.void renderText(){    //Free the old text surface.   SDL_FreeSurface(scoreCount);           //Convert from 'int' to string here. (I usually wrap it into a function)   std::string text = "Score: " + intToString(score);        //Re-create the surface. (c_str() is the std::string function used to convert to the old 'C' style string of type char*)   //I assume you already loaded 'myFont'   scoreCount = TTF_RenderText_Solid(scoreFont, text.c_str(), textColor);   if(scoreCount == NULL)       printf("Error in function 'TTF_RenderText_Solid': %s\n", TTF_GetError());   applySurface(600, 180, scoreCount, screen);   SDL_Flip(screen);

Here is the intToString function
// convert the int to a stringstd::string intToString(int n){	std::stringstream sstream;	sstream << n;	return sstream.str();} // end intToString

I do not need the if statement because it is only called when a row is full so the score will always have changed but its weird because it does not look like the word score is overwritten. Just the actual number

##### Share on other sites
Quote:
 Original post by cwl157I do not need the if statement because it is only called when a row is full so the score will always have changed but its weird because it does not look like the word score is overwritten. Just the actual number

Your problem exists not because the rendering-text code is wrong, but because you never clear the screen. The reason why the word 'Score: ' doesn't appear to be overwritten, is because it overwrites itself so exactly that you can't tell it's being overwritten. (It overwrites pixel-perfectly ontop of itself each time)

Want a quick and dirty solution? Use this:

void renderText(){    //You don't need this the way you are currently using it, because   //you only use it in this function. So I commented it out to show you.   //You can just delete it entirely, and this comment too.   //SDL_FreeSurface(scoreCount);       std::string text = "Score: " + intToString(score);        //We create the surface here, and free it here, since you only use it in this one function.   SDL_Surface *scoreCount = TTF_RenderText_Solid(scoreFont, text.c_str(), textColor);   if(scoreCount == NULL)       printf("Error in function 'TTF_RenderText_Solid': %s\n", TTF_GetError());      //Before we draw the text, we'll draw a blank rectangle under it, to cover up the old text.   SDL_Rect rect;   rect.x = 600;   rect.y = 180;   rect.w = 150; //Change this, to change how wide the black box under the score is.   rect.h = 20; //Change this, to change how *tall* the black box is.      //To change the color of the box here, you can change the number '0x000000' to any other Hexidecimal color you like.   //0x-00-00-00 = 0x-Red-Green-Blue. 00 is 0, FF = 255. '0x' means it's in Hex format.   SDL_FillRect(screen, &rect, 0x000000 /* RGB color, in Hexidecimal */);      applySurface(600, 180, scoreCount, screen); //Draw the image.   SDL_FreeSurface(scoreCount); //Free the image after we're down.      SDL_Flip(screen); //Flip the screen, showing the new images.}

That is a crude way to do it, but I recongize that when you are learning something, sometimes you just want to get it up and running, without caring about how it works underneath.

If you *do* care, I have alot of things to say, so bear with me.

First, you're not supposed to call SDL_Flip(screen) every time you draw something. You're supposed to do it once per 'frame' after you finish drawing. Doing it after every draw might cause flickering, or at the very least, probably slows it down a good deal.

Second, you should keep most your drawing code together, and not spread it out over your project. This helps in several ways; first, it makes it easier for you to expand to draw more objects, second, it helps keep your code looking cleaner, third, it helps isolate bugs, fourth, it helps you figure out what's going on, incase you forget sometime in the future.

Your program should be split into two or more phases/chunks, with 'draw' being one of them. I personally split my projects into three phases, like this:

Phase 1: Get Player Input, Deal with Input.
Phase 2: Update everything that needs to be updated, such as moving objects.
Phase 3: Draw everything that needs to be drawn.

You could make Phase 1 and Phase 2 the same phase if you like, but Draw should definately be it's own.

My main loop usually looks like this: (well, more or less, when you boil down to it)
bool Quit = false;void EventFunction();void UpdateFunction();void DrawingFunction();int main(int argc, char *argv[]){    //Init code goes here. Things like 'SDL_Init' or loading fonts and images.    //You can also setup the window here. (SDL_CreateVideoMode())        while(Quit == false) //I actually prefer 'while(!Quit)' but that doesn't affect the code itself.    {        EventFunction();        UpdateFunction();        DrawingFunction();                SDL_Delay(20);    }        //Quiting code goes here. Things like 'SDL_Quit()' and     //SDL_FreeSurface()-ing my images, and TTF_CloseFont()-ing my fonts.}void EventFunction(){    //Keep all your event input in one place. }void UpdateFunction(){    //Keep all your updating code in one place.}void DrawingFunction(){    //Keep all your drawing in one place.        //Start by drawing over your old screen entirely in black, to 'erase' all old images.    SDL_FillRect(screen, NULL, 0x000000);        ...        //Anything you have to draw would go here. (Enemies, objects, the player, text, buttons, etc...)        ...        //Only flip the surface at the very end of all your drawing.    SDL_FlipSurface(screen);}

This way, you keep all your drawing code organized and together in one spot, all your event code together+organized, all your updating code together+organized. This is a good way to do things, until you learn about classes.(In which case, you'll probably want each class to have it's own 'event', 'update', and 'draw' functions)

After getting it working, you'll probably be interested in properly timing your code as well, so everything moves at the correct speed. If so, you could ask here, or create a new thread for that. If I was you, I'd look at merely limiting your frames to 30 or 40 a second, at least for now.

I also, strongly recommend you read these tutorials. This article, for example, goes over what I just said: Game Loops.

##### Share on other sites
ok i did this:

SDL_FillRect(screen, NULL, 0x000000);

in the beginning of the loop and then i call SDL_Flip(screen) at the very end of the loop and everything seems to work great.

##### Share on other sites
Excellent. Glad we could be of help.

• 11
• 20
• 12
• 10
• 38
• ### Forum Statistics

• Total Topics
631401
• Total Posts
2999864
×