-1

I'm having an issue with a program I'm working on. Occasionally, it will just freeze. No errors or anything.

The game is a multiplayer game where you fly a ship around. Pictures of other players and powerups move in and out of view depending on your location. For the most part, it works great, but under certain circumstances, it locks up.

I've tracked it down to when it BLITs one surface onto another. (SDL_BlitSurface).

If I comment out the single line of code where it blits (SDL_BlitSurface), and replace the graphic with a simple circle, it'll never freeze under any circumstances. But, comment out the circle and replace it with blitting the graphic again, and it'll randomly freeze. The frustrating part is, sometimes it will, sometimes it won't. Sometimes the graphic will sit on screen for a few moments and then freeze, sometimes it'll freeze the moment it shows up. Sometimes, it won't freeze at all. I simply cannot track it down to anything in particular.

I have ample amount of code that checks for NULL surfaces and it doesn't seem to stop it. I also have it set up to output information about all the graphics to a file (such as width, height, location in memory, x, y, etc) and nothing seems out of the ordinary.

My main questions are, what about surfaces can cause SDL_BlitSurface to freeze? And what other checks can I add for surfaces to make sure it doesn't try to blit bad surfaces?

The code is too long to list, but here is how it works:

class Player
{
    Player();

    int x;
    int y;
    int xvel;
    int yvel;
    SDL_Surface *DrawScreen;
    SDL_Surface *ShipPic;

    void check_player_dist();
    void check_powerup_dist();
    void update();
};    

class PowerUp
{
    int x;
    int y;
    int type;
    SDL_Surface *Powerup_Pic;
};

Player::Player()
{
    Apply_Surface(0, 0, PlayerShipPics, ShipPic);
}

Player::Update(Player p[], PowerUp pu[])
{
    x += xvel;
    y += yvel;

    for (int i = 0; i < Num_Players; i++)
    {
        if (check_on_screen(p[i].x, p[i].y) == true)
        {
            Apply_Surface(x - p[i].x, y - p[i].y, p[i].ShipPic, DrawScreen);
        }
    }

    for (int i = 0; i < Num_PowerUps; i++)
    {
        if (check_on_screen(pu[i].x, pu[i].y) == true)
        {
            Apply_Surface(x - pu[i].x, y - pu[i].y, pu[i].Pic, DrawScreen);
        }
    }
}


int main()
{
    SDL_Surface *Screen;
    Player players[4];
    PowerUp powerups[200];
    Num_Players = 4;
    Num_PowerUps = 200;

    while (quit == false)
    {
        for (int i = 0; i < Num_Players; i++)
        {
            players[i].update(players, powerups);
            switch (i)
            {
                case 0: ScreenX = 0; ScreenY = 0; break;
                case 1: ScreenX = ScreenWid / 2; ScreenY = 0; break;
                case 2: ScreenX = 0; ScreenY = ScreenHigh / 2; break;
                case 3: ScreenX = ScreenWid / 2; ScreenY = ScreenHigh / 2; break;
            }
            Apply_Surface (ScreenX, ScreenY, players[i].DrawScreen, Screen);
        }

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

void Apply_Surface (int x, int y, SDL_Surface* Source, SDL_Surface* Destination, SDL_Rect* Clip)
{
    SDL_Rect Offset;

    Offset.x = x;
    Offset.y = y;

    if ((Source != NULL) && (Destination != NULL))
    {
        SDL_BlitSurface (Source, Clip, Destination, &Offset );
    }
}

I've noticed it generally freezes when two or more players are near each other and it tries to draw the same power-up on both of their screens. But again...not always!

genpfault
  • 51,148
  • 11
  • 85
  • 139
Justin Lloyd
  • 123
  • 3
  • 11
  • * what about surfaces can cause SDL_BlitSurface to freeze*: anything really. Posting your code would help. –  Jun 18 '13 at 20:30
  • There's too much code to post, but I've added some pseudo-code to show how it works. As said, the program itself runs great. It's simple *sometimes* when blitting a graphic onto a drawing surface, it freezes. I cannot find anything identifiable about the circumstances it freezes. Nothing about either surface is out of line. And it is very definitely the actual SDL_BlitSurface line of code that it freezes on. – Justin Lloyd Jun 18 '13 at 21:27
  • You question is too vague. Reduce your problem to a specific part of the code that you think is giving you the problem. –  Jun 18 '13 at 21:50
  • Can you post the code around the actual misbehaving BlitSurface call? – jaymmer - Reinstate Monica Jun 19 '13 at 13:02

2 Answers2

1

Well, I figured out what it was.

I was using the SDL_GFX library along with my game. Many of the images were created using rotozoomSurface(), which is a function of SDL_GFX.

Turns out there's a bug in it where, under certain circumstances that I don't know, it'll create a bad surface that will work "most" of the time, but under the right conditions, will crash. Such as, being placed at a particular x & y coordinate on the screen. (Don't know for sure). The rotated/zoomed images would work about 95% of the time, so it was very difficult to pin point what the issue was.

The work around was, when the image was created, just SDL_BlitSurface() it onto another surface under controlled conditions, such as putting it at coordinates (0, 0). Then, delete the rotated and zoomed surface, and just use the new "safe" surface.

Works great after that.

Hopefully this will help anyone who's using SDL_GFX and cannot figure out why their program is crashing.

Example:

Before:

SDL_Surface *original = SDL_CreateRGBSurface(SDL_SWSURFACE, Ship_Width, Ship_Height, Screen_BPP, 0, 0, 0, 0);
Apply_Surface(0, 0, ShipsPic, original, &bounds);

SDL_Surface *finished = rotozoomSurface(original, pic_angle, zoom, SMOOTHING_ON);
SDL_FreeSurface(original);
return finished;

After (fixed):

SDL_Surface *original = SDL_CreateRGBSurface(SDL_SWSURFACE, Ship_Width, Ship_Height, Screen_BPP, 0, 0, 0, 0);
Apply_Surface(0, 0, ShipsPic, original, &bounds);

SDL_Surface *temp = rotozoomSurface(original, pic_angle, zoom, SMOOTHING_ON);
SDL_Surface *finished = SDL_CreateRGBSurface(SDL_SWSURFACE, temp->w, temp->h, Screen_BPP, 0, 0, 0, 0);

Apply_Surface(0, 0, temp, finished);
SDL_FreeSurface(temp);
SDL_FreeSurface(original);
return finished;

And for what it's worth, the Apply_Surface() function:

void Apply_Surface (int x, int y, SDL_Surface* Source, SDL_Surface* Destination, SDL_Rect* Clip)
{
    SDL_Rect Offset;

    Offset.x = x;
    Offset.y = y;

    if ((Source != NULL) && (Destination != NULL))
    {
        SDL_BlitSurface (Source, Clip, Destination, &Offset );
    }
}
Justin Lloyd
  • 123
  • 3
  • 11
0

There's not really enough information to figure out what exactly is going on. Computers don't like to do things "sometimes," they either do them or not, so it leads me to believe that maybe there's some variable that's doing something it shouldn't.

Just in case, what does your Apply_Surface() function look like? I assume that's where you're doing your actual blitting, and if that's where you're having your problems, that would be useful for those of us trying to figure out your dilemma.

The Posh Ferret
  • 126
  • 1
  • 5
  • Thanks for the reply. The "sometimes" it's what's got me pulling my hair out. I can get rid of most everything that's random except for the graphic's location on screen and, as said, sometimes it'll be just fine, and sometimes it'll freeze. Sometimes it'll display the graphic just fine, sometimes, it'll display the exact same graphic for just a second, and then lock up. I posted the code for the Apply_Surface. There's nothing fancy about it. – Justin Lloyd Jun 20 '13 at 20:58
  • What I find odd is that if I have, for example, if (player[i].ID == 1) { Apply_Surface(...); } it won't lock up at all. It'll post graphics to ONLY player 1's screen over and over again. Same for player 2, or 3, or 4, etc. It's when ALL players are allowed to update their SDL_Surfaces with graphics that it'll freeze. This is why I'm stumped. Each player is an object, and there's no coding difference between player 1, 2, 3, etc. I don't know what more code to post, which is why I asked about SDL_BlitSurface in particular. – Justin Lloyd Jun 20 '13 at 21:14