• ### Announcements

• #### Wondering what's new and changed at GameDev.net?06/20/17

Check out the latest Staff Blog update that talks about what's changed, what's new, and what's up with these "Pixels".
Followers 0

# Im making a line break sdl_ttf function in c for a rpg game

## 8 posts in this topic

Heres the function

    SDL_Surface *draw_wordbreak( char *input) {

char *token;
int drawY = 0;
SDL_Surface *tempSurface = NULL;

printf("Splitting string in to tokens : %s \ninto tokens:\n", input);
token = strtok(input,",");
while(token != NULL) {
printf("TOKEN : %s \n",token);

SDL_Surface *txtTmp = NULL;
txtTmp = TTF_RenderText_Solid(base_font, token, blueColor);
apply_surface(0,drawY,txtTmp,tempSurface);
SDL_FreeSurface(txtTmp);

token = strtok(NULL,",");
drawY += 20; // move the next line down
}

return tempSurface;

}


this is from the main file

// the data to be made in to text
char tempData[100] = "this is some example,Data to show off the wordbreak,Function for the sdl_ttf";

// setup the surface for the text to be transfer to
SDL_Surface *story_text_001;

// where the function is used
story_text_001 = draw_wordbreak(tempData);

// then in the render loop is where it should get applied
apply_surface(85,85,story_text_001,screen);

// screen is the display device and apply_surface works fine it been tested with many
// others sdl surfaces 

When i do this the story_text_001 surface does not have any text like it should ?

Edited by MrPhoenix
0

##### Share on other sites
"tempSurface" is NULL. Your call to apply_surface, which presumably ends up calling SDL_BlitSurface(), does not allocate a surface. Indeed, it cannot even if it tried - in C parameters are passed by value and cannot be modified by the callee:
void foo(int parameter) {
parameter = 42; // Change is local to the function - parameter is a distinct copy of the caller's argument.
}

// Later
int x = 1;
printf("X: %d\n", x); // Will print "1"
foo(parameter);
printf("X: %d\n", x); // Will print "1"


This even applies to pointers (but not pointees):
void bar(int *pointer) {
*pointer = 42; // Modifies pointee, will be visible to caller
pointer = NULL; // Local change, not visible to caller
}

// Later
int x = 1;
int *p = &x;
printf("X: %d\n", x); // Will print "1"
printf("P: %p\n", p); // Will print some address in hex
bar(parameter);
printf("X: %d\n", x); // Will print "42"
printf("P: %p\n", p); // Will print the same hex as above

So SDL_BlitSurface() is not capable of modifying the pointer passed to it.

One option is to use SDL_CreateRGBSurface() in draw_wordbreak(). This is complicated by the fact that you'd need to know how big to make the surface. Another option is to draw directly to the screen in draw_wordbreak(). Edited by rip-off
1

##### Share on other sites

ill try a couple things rip-off ill repost here in a minute

0

##### Share on other sites

Thanks rip-off i now fixed the function

    SDL_Surface *draw_wordbreak( char *input, int width, int height) {

char *token;
int drawY = 0, surW = width, surH = height;
SDL_Surface *tempSurface,*txtTmp = NULL;

printf("Splitting string in to tokens : %s \ninto tokens:\n", input);
token = strtok(input,",");
while(token != NULL) {
printf("TOKEN : %s \n",token);

txtTmp = TTF_RenderText_Solid(base_font, token, blueColor);
apply_surface(0,drawY,txtTmp,tempSurface);
SDL_FreeSurface(txtTmp);

token = strtok(NULL,",");
drawY += 20; // move the next line down
}

return tempSurface;

}

0

##### Share on other sites

Excellent job! I have several suggestions for improvements:

• In general, variables should not be declared until they are needed. It's considered bad practice to declare all your variables at the top of a function.
• I don't see surW and surH being used anywhere. Unused variables should be automatically detected and reported by your compiler if you have it's warnings set to the highest.
• I don't see any reason why 'surW' needs to copy 'width', and why you can't just use 'width' directly.
• Instead of hardcoding 'rmask', 'gmask', and etc... you should use the screen surface's masks, so no conversion needs to take place for every blit.
• Instead of hardcoding '640' and '480', you should calculate the actually amount of space it'll require, and use that (Note: this can get difficult).
• Instead of increasing 'drawY' by 20, you should increase it by the height of the line itself so '20' isn't hardcoded (because you might use a larger font later). I haven't used SDL_ttf in several years, but TTF_FontLineSkip() sounds like it'll return the right amount if you have that function available.
• base_font appears to be a global. Why not pass in the font to 'draw_wordbreak', allowing you to use the same function for different fonts in your program?

You also use three different variable naming schemes:

1) Super abbreviated camel-case: surW, surY, txtTmp

2) Decently abbreviated camel-case: tempSurface (My personal preference - I don't like absurd abbreviations)

3) Underscored variable names: base_font, story_text_001, draw_wordbreak, apply_surface (though the last two are function names, so it makes to have a different style for them)

(If you want to get super technical, rmask, gmask, bmask, and amask use a 4th naming scheme, but they're so small that that can be ignored)

I'm not trying to nitpick your code, just pointing out some hidden problems that could bite you later!

Best of luck on your RPG project!

[offtopic] What kind of RPG is it? I'm working on one myself. *points at signature*

1

##### Share on other sites

[quote name='Servant of the Lord' timestamp='1358717589' post='5023631']
In general, variables should not be declared until they are needed. It's considered bad practice to declare all your variables at the top of a function.
[/quote]
As an addendum, I'd like to clarify this to "In general, variables should not be declared until the start of the block where they are needed."

Depending on your version of C, you can only declare variables at the start of a block scope. I do agree that it is likely best practice to put variable declarations in the innermost block, but it drives me nuts when someone declares a variable in the middle of a block; not only is it not valid C89, but I often miss its declaration when reading code, resulting in confusion. The only exception I make so far is in C++, where the construction of an object depends upon the result of a computation in that block, to avoid default constructing, then doing another initialization or construction. If it makes no difference where it is placed, then I place it at the start of the block.

1

##### Share on other sites
Depending on your version of C, you can only declare variables at the start of a block scope.

Thanks, I didn't realize that. I'm a C++ coder, so I tend to think of 'C' as "C++ without classes".

0

##### Share on other sites
Depending on your version of C, you can only declare variables at the start of a block scope.

Thanks, I didn't realize that. I'm a C++ coder, so I tend to think of 'C' as "C++ without classes".

0