Surface Not Blitting

Hello,

I am having some problem with getting a image to blit. The FPS text image shows up or is blitted, but when I try to blit the point text image to the surface it won’t blit. I’ll post my code.

Code:

#include “main.h”

SDL_Surface* Screen;
SDL_Event event;
TTF_Font* Font;

int ThisTime = 0;
int LastTime = 0;
float DeltaTime = 0.0f;

const int WIDTH = 800;
const int HEIGHT = 600;
const int DEPTH = 32;
const char* TITLE = “Tower Defense”;

SDL_Color textColor = {255,255,0};

int TowerHealth = 100;
int Points = 0;

SDLKey keyPressed;
SDLKey keyReleased;

bool keysHeld[323] = {false};

bool GameRunning = true;

SDL_Surface* Backdrop;
SDL_Rect BackdropRect;

SDL_Surface* FPS;
SDL_Rect FPSRect;
char fps[10];

SDL_Surface* POINT;
SDL_Rect POINTRect;
char point[6];

bool GameScreen = true;

int main(int argc, char* argv[])
{
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return 1;
}

Screen = SDL_SetVideoMode(WIDTH,HEIGHT,DEPTH, SDL_HWSURFACE);
SDL_WM_SetCaption(TITLE,NULL);

if(TTF_Init() == -1)
{
    return 1;
}

if(Mix_OpenAudio(22050,MIX_DEFAULT_FORMAT,2,4096) == -1)
{
    return 1;
}

Backdrop = IMG_Load("Backdrop.png");
BackdropRect.x = 0;
BackdropRect.y = 0;
BackdropRect.w = 800;
BackdropRect.h = 600;

Font = TTF_OpenFont("Arial.ttf",20);

FPSRect.x = 1;
FPSRect.y = 1;
FPSRect.w = 0;
FPSRect.h = 0;

POINTRect.x = 1;
POINTRect.y = 60;
POINTRect.w = 0;
POINTRect.h = 0;

while(GameRunning)
{
    ThisTime = SDL_GetTicks();
    DeltaTime = (float)(ThisTime - LastTime) / 1000;
    LastTime = ThisTime;

    sprintf(fps,"FPS: %.4f", DeltaTime);
    FPS = TTF_RenderText_Solid(Font,fps,textColor);

    sprintf(point,"Points: %.3d", Points);
    POINT = TTF_RenderText_Solid(Font,point,textColor);

    while(SDL_PollEvent(&event))
    {
        if(event.type == SDL_QUIT)
        {
            GameRunning = false;
        }

        if(event.type == SDL_KEYDOWN)
        {
            keyPressed = event.key.keysym.sym;

            if(keyPressed == SDLK_ESCAPE)
            {
                GameRunning = false;
            }
        }
    }

    if(SDL_Flip(Screen) == -1)
    {
        return 1;
    }

    SDL_FillRect(Screen,NULL,SDL_MapRGB(Screen->format,0,0,0));

    SDL_BlitSurface(Backdrop,NULL,Screen,&BackdropRect);
    SDL_BlitSurface(FPS,NULL,Screen,&FPSRect);
    SDL_BlitSurface(POINT,NULL,Screen,&POINTRect);
}

free(fps);
free(point);

SDL_FreeSurface(FPS);
SDL_FreeSurface(Backdrop);
SDL_FreeSurface(POINT);

TTF_CloseFont(Font);
TTF_Quit();
Mix_CloseAudio();
SDL_Quit();

return 0;

}

This is what is displayed in the debugger.

Code:

Output to Display…
"[New Thread 3992.0x12dc]\n"
Stopped - signal received
Thread 1 stopped in ?? at line 5823711 in with Segmentation fault
Debugger closed.

[/code]

Use of the API looks ok, but you should do some error checking on your pointers.
Maybe your background is invalid and you gave it to SDL which causes the
segmentation fault.________________________________
From: g_andy@live.com (GameCoder)
To: sdl at lists.libsdl.org
Sent: Thu, March 22, 2012 4:00:42 PM
Subject: [SDL] Surface Not Blitting

Hello,

I am having some problem with getting a image to blit. The FPS text image shows
up or is blitted, but when I try to blit the point text image to the surface it
won’t blit. I’ll post my code.

I don’t know if it was the pointers or not, but I got it to work. Where it says point[6], I changed it to point[10], and now it works. Is that something that it has to do with how C++ handles char?

So in this line you are trying to write more chars than your array is defined
for. sprintf does not protect you from doing this, you could use snprintf to
limit the number of bytes written to the array. So basically you overflowed your
buffer. Making it larger of course fixed the problem.

sprintf(point,“Points: %.3d”, Points);________________________________
From: g_andy@live.com (GameCoder)
To: sdl at lists.libsdl.org
Sent: Thu, March 22, 2012 4:43:43 PM
Subject: Re: [SDL] Surface Not Blitting

I don’t know if it was the pointers or not, but I got it to work. Where it says
point[6], I changed it to point[10], and now it works. Is that something that it
has to do with how C++ handles char?

Ah, I see. Thanks for the tip.

Again, a language issue rather than a SDL issue, but you should not
free() arrays that were not allocated by malloc() or realloc().

To summarize and put it in other words, in case you’re not that experienced
with C++…

You should store enough space for your strings:
char point[6]; // stores only 5 characters and a null terminator

You should use snprintf() to safely buffer text:
snprintf(point, 6, “Points: %.3d”, Points); // Gives you the text "Point"
instead of a segfault

You should not free() memory that you allocated on the stack (declaring a
char[6] variable is just like declaring an int variable; you wouldn’t
free() that). free() is for “heap” memory that is requested using malloc()
and friends.

Now, the above advice is all C advice. For C++:

Do not use char[] or char* to store strings. One option is using
std::string, the STL string class.

Do not use malloc() or free() ever. Use operators new, delete, and
delete[].

And other stuff to throw in… Be sure that every allocation is matched by
a deallocation. In your while(GameRunning), you are leaking a lot of
memory because you are not freeing FPS and POINT every frame, but you are
creating new SDL_Surfaces to point at.

I also recommend that you move your SDL_Flip() after the drawing calls.
You are flipping old screen data after handling events, so you are showing
the player a world that lags behind by a frame.

Jonny D

Thanks for the advice. Though you say I should put the SDL_Flip after the drawing calls. Where exactly should the SDL_Flip() be then? I have it at the bottom there, so that everything gets drawn when I need it to. I also know I should probably be more organized and use OOP, but this was a small project and was more for practice and fun.

GameCoder wrote:

Where exactly should the SDL_Flip() be then?

Do the flip after you have drawn everything, so change this:

Code:
if(SDL_Flip(Screen) == -1)
{
return 1;
}

SDL_FillRect(Screen,NULL,SDL_MapRGB(Screen->format,0,0,0));

SDL_BlitSurface(Backdrop,NULL,Screen,&BackdropRect);
SDL_BlitSurface(FPS,NULL,Screen,&FPSRect);
SDL_BlitSurface(POINT,NULL,Screen,&POINTRect);

To this

Code:
SDL_FillRect(Screen,NULL,SDL_MapRGB(Screen->format,0,0,0));

SDL_BlitSurface(Backdrop,NULL,Screen,&BackdropRect);
SDL_BlitSurface(FPS,NULL,Screen,&FPSRect);
SDL_BlitSurface(POINT,NULL,Screen,&POINTRect);

if(SDL_Flip(Screen) == -1)
{
return 1;
}

Also, add double buffering to prevent flickering. You can do this by adding the SDL_DOUBLEBUF flag in your SDL_SetVideoMode call:

Code:
Screen = SDL_SetVideoMode(WIDTH,HEIGHT,DEPTH, SDL_HWSURFACE|SDL_DOUBLEBUF);------------------------
The Legend of Edgar. A 2D platformer for Windows and Linux. (http://www.parallelrealities.co.uk/p/legend-of-edgar.html)

Thanks for the help. Stuff is running smoothley now.