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

Started by
7 comments, last by Servant of the Lord 11 years, 2 months ago

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 ?

Advertisement
"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().

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

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;
        Uint32 rmask = 0xFF000000, gmask = 0x00FF0000, bmask = 0x0000FF00, amask = 0x000000FF;

        tempSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 640, 480, 32, rmask, gmask, bmask, amask);

        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;

    }

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! wink.png

Best of luck on your RPG project!

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

[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.

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". laugh.png

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". laugh.png

this is the project http://www.gamedev.net/blog/1611/entry-2255802-teaser-page-with-updated-information-and-story-line/

i would like to know about your rpg ??

Here is my GameDev.net Journal, and here is the website with a description about the game.

Yours looks nice. I commented on your journal.

This topic is closed to new replies.

Advertisement