Sign in to follow this  

SDL -- Incorrect output value

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Currently im writing a scrolling shooter game. Thanks to your help , im going to finish it soon. This time , a weird problem(maybe?) came up. I use this function to update the status on the screen:
Quote:
int updStatus() { stats_text = TTF_RenderText_Blended(font_name, "Life:"+life, txt_col ); UPDATE_POSITION( 0, 0, stats_text, screen ); }
The output should be : "Life: and the stored value of (int) life". Well , the output is this : [img]http://img133.imageshack.us/img133/143/alienhunteri7ov.jpg[/img] (direct link:http://img133.imageshack.us/img133/143/alienhunteri7ov.jpg) How can i fix it ??

Share this post


Link to post
Share on other sites
I would try concatinating both into a sstream before hand and trying to render that. My guess is that, since TTF_RenderText_Blended() is expecting a char* as its second parameter, it doesn't know how to deal with the concatination your trying to do.

Share this post


Link to post
Share on other sites
Yes, sstream it. You are passing an int to a string or char array, so you first need to convert the int to a string.


#include <sstream>

...

std::stringstream ssLife;
int iLife;
std::string sLife
...

ss << "Hits left: ";
ss << iLife;
sLife = ss.str();

stats_text = TTF_RenderText_Blended(font_name,
sLife, txt_col );
...


Something like that.

Share this post


Link to post
Share on other sites
Thanks :) , it worked.

Quote:

int updStatus() {
std::stringstream ss;
std::string sLife;
ss << "Life: ";
ss << life;
sLife = ss.str();

stats_text = TTF_RenderText_Blended(font_name,
sLife.c_str(), txt_col );

UPDATE_POSITION( 0, 0, stats_text, screen );
}

The only thing needed change was "sLife" -> "sLife.c_str()".

Share this post


Link to post
Share on other sites
hmm..

After i included this function to my main() ,another problem appeared!

When im running the game for about 5-10 minutes the system starts lagging and the window freezes!.
Why this happens?

PS: Without this function the program works great...

Share this post


Link to post
Share on other sites
You have a memory leak! Each time you call TTF_RenderText_Blended it returns a pointer to a new SDL_Surface. You must always free it with SDL_FreeSurface:

int updStatus()
{
std::stringstream ss;
std::string sLife;
ss << "Life: ";
ss << life;
sLife = ss.str();

stats_text = TTF_RenderText_Blended(font_name,
sLife.c_str(), txt_col );

UPDATE_POSITION( 0, 0, stats_text, screen );
SDL_FreeSurface( stats_text );
}


Good luck finishing your game!

Share this post


Link to post
Share on other sites
Quote:
Original post by vman
hmm..

After i included this function to my main() ,another problem appeared!

When im running the game for about 5-10 minutes the system starts lagging and the window freezes!.
Why this happens?

PS: Without this function the program works great...


I find it hard to believe that your program compiled without using .c_str()...

Were there no errors? Warnings?

Your problem is you are leaking surfaces. Use SDL_FreeSurface() on the surface returned from TTF_RenderText_*().

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
Quote:
Original post by vman
hmm..

After i included this function to my main() ,another problem appeared!

When im running the game for about 5-10 minutes the system starts lagging and the window freezes!.
Why this happens?

PS: Without this function the program works great...


I find it hard to believe that your program compiled without using .c_str()...

Were there no errors? Warnings?



As i said , the only thing that i've changed is .c_str() pointer.

[QUOTE=ME]
The only thing needed change was "sLife" -> "sLife.c_str()".
[/quote]
If you still dont believe me , here's the proof :
(WARNING: thats the bugged version)
http://rapidshare.de/files/23041026/Alien_Hunter_bugedVER.zip.html

Share this post


Link to post
Share on other sites
To avoid constantly reallocating and freeing the surface, you may consider keeping a 'static' (in the sense of outliving the function) surface around, and re-creating it only when the 'life' value changes. There are numerous approaches to this, and usually OO techniques would be shown; but in the interest of keeping the example as simple as possible:


int updStatus() {
// The value (if any) that was rendered last time.
static int renderedLife;
// It looks like you already have a global, or otherwise wider-scoped,
// 'stats_text' for the surface. I will use that one...

if (stats_text && (life != renderedLife)) {
// there is an invalid surface to clean up.
SDL_FreeSurface(stats_text);
}
if (!stats_text) {
// either it was just cleaned up, or this is the first run.
// Cache the rendered life value so we know for next time.
renderedLife = life;
// Set up the surface. Note a couple of techniques here ;)
std::stringstream ss("Life: ");
ss << life;

stats_text = TTF_RenderText_Blended(font_name, sLife.str().c_str(), txt_col);
}
// I really hope this isn't a macro :(
UPDATE_POSITION( 0, 0, stats_text, screen );
}


Of course, you normally only optimize when you need to, and making sure you don't leak memory may well be optimization enough - but I thought you should be familiar with this sort of technique in general, because some "resources" (like SDL surfaces) can be very expensive to acquire, depending on your environment.

Share this post


Link to post
Share on other sites
Thanks zahlman ;).

Because i hate copy & paste , i edited your code to this :

Quote:

//if surface == null
if (!stats_text){
stats_text = TTF_RenderText_Blended(font_name,
sLife.c_str(), txt_col );
//update surface :x,y,surface, @ screen
UPDATE_POSITION( 0, 0, stats_text, screen );
}

//if stats_text !=null
if (stats_text){
//release = sdl_freesurface()
RELEASE_( stats_text );
//set it to null
stats_text = NULL;
}

There are no problems now :).

Share this post


Link to post
Share on other sites
Hi again [totally].

This time i wont ask for help , just for a suggestion.

I've got this code (please read the comment lines)

//------------------- FUNCTION LOAD() -------------\\

//Insert 100 image objects into Enemy array.
//max data = 100
for (int en=0;en<101;en++){
//load the image & remove the background color
Enemy[en] = load_image("Data\\enemyA.png");
//if enemy array surface !=null
if (Enemy[en]){
//set the EnemyX array position to Screen_width
// +en * its width.
//max data =100
EnemyX[en] =SCREEN_WIDTH +en *Enemy[en]->w;
}
}





//------------------- -------------- -------------\-
//------------------- MOVE ENEMY() -------------\\


//---This is just a test...i'll add more movement rutines later..
//move only the 1/10 wave of enemies
for (int e=0;e<11;e++)
{
// increase x pos forward by [1]
EnemyX[e] -=1;
//update surface..
UPDATE_POSITION( EnemyX[e], EnemyY[e], Enemy[e], screen );
}





//------------------- -------------- -------------\My question is : Should i release(using Free_surface()) the
surface array ? or no?
Im asking because i dont want to cause memory leaks on slow machines.

And another thing...
Im going to write a simple collision detection function , and i would like to
know what do i have to do in order to hide the enemy's object.
I think i have to remove the BLIT_SURFACE() while applying surface's position.
Am i right?
---------------------------

Thats it [dead].
Sorry for asking alot , but its the first time im writing a game (well , im on the 6-7th day) , so please understand me [wink].

ThankS.

PS: Here's a screenshot:
:)
{direct link:http://img81.imageshack.us/img81/9251/ahunter22hp.jpg}

Share this post


Link to post
Share on other sites
The rewrite misses the point of my code (although it should still work).

When you call an SDL creation function, it allocates some stuff and gives you a pointer to the allocated stuff. Later you clean up the stuff with a matching SDL function.

If you iteratively allocate something (i.e. reassigning the pointer to the result of another call), you need to iteratively clean it up (i.e. cleaning up with the current pointer value before you reassigne it). However, you could swap two pointer values without problem (assuming you swap them correctly).

If you allocate something once and *use* the resource multiple times, then you can keep the pointer set as it is, and only clean up when you're done with your uses.

In the case of the Enemy array, assuming you just leave all those entries in the array alone during the "main loop", then you would just free the surfaces after the main loop, matching the creation before the main loop.

In the code I provided, the idea is to track what the current resource *represents*, so that you can use it several times until you determine that you need it to represent something else. When that happens, you can clean up that resource, and recreate a new one representing the new thing ("thing" here being the rendered text "Life: " followed by the numeric data).

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this