1

I'm trying to write a simple game in C. I use SDL2 to draw stuffs. Here is a main loop:

...
while( !quit_f )
{
    //Handle events on queue
    while( SDL_PollEvent( &e ) != 0 )
    {
        //User requests quit
        if( e.type == SDL_QUIT )
        {
            quit_f = 1;
        }
    }
    currTime = clock();
    dt = (float)((currTime - t)/1000.0f);
    update_player(dt, player);

    printf("locks before drawing: %i\n", player->surface->locked );
    draw_player(player);

    printf("\n");
    printf("%p\n", player->surface);
    printf("locks before window update: %i\n", player->surface->locked );

    //Update window surface
    SDL_UpdateWindowSurface( window );

    printf("%s\n", SDL_GetError());
    printf("locks after window update: %i\n", player->surface->locked );
    printf("\n");
    t = currTime;
}
...

Here is the draw_player function:

void draw_player(struct GameObject * self){
    printf("%p\n", self->surface);
    printf("locks iside draw_player - before blit: %p\n", self->surface->locked);
    SDL_BlitSurface(window, NULL, self->surface, NULL);
    printf("locks iside draw_player - after blit: %p\n", self->surface->locked);
}

It compiles fine but it does not display player after running it. Output:

locks before drawing: 0
0x89795b0
locks iside draw_player - before blit: (nil)
locks iside draw_player - after blit: (nil)

0x89795b0
locks before window update: 0
Surfaces must not be locked during blit
locks after window update: 0

I don't get why is self->surface->locked NULL inside draw_player function. Pointers to the surface are the same, so... I don't really get it. I don't call SDL_LockSurface anywhere in my code but SDL complains that surface is locked during blit - Surfaces must not be locked during blit. I tried to call SDL_UnlockSurface before SDL_BlitSurface but nothing changed. Any ideas? I have to note that I am begginer in C and SDL. I run Fedora 24. Since SDL is cross-platform lib it should not be a problem. I use gcc 6.1.1.

Player's sprite is in png format that is why I use IMG_Load. Here is how player is created:

void init_player(struct GameObject * player, char * path, float x, float y){
    SDL_Surface * image = IMG_Load(path);
    if(image == NULL){
        printf("Error while loading png: %s\n", IMG_GetError()); 
        return;
    }

    // direction vector
    player_dir = malloc(sizeof(Vector2d));
    player_dir->x = 0.0f; 
    player_dir->y = 0.0f;

    // destination rectangle
    SDL_Rect * dRect = malloc(sizeof(SDL_Rect));
    dRect->x = round(x);
    dRect->y = round(y);
    dRect->w = image->w;
    dRect->h = image->h;

    player->surface = image;
    player->destRect = dRect;
    player->x = x;
    player->y = y;
    player->width = image->w;
    player->height = image->h;    
    player->update = update_player; // function pointer
    player->draw = draw_player; // function pointer
}

And last thing I have to tell you. I store pointers to draw and update functions in the GameObject struct. So I call update_player like player->update(...). It's the same with draw functions. It is a bit hacky style but I like it. I tried to call draw_player right away. Since a result was the same I think my coding style is not a problem. But I might be wrong. Feel free to correct me.

EDIT: I might found that bug. SDL_BlitSurface(window, NULL, self->surface, NULL); should be SDL_BlitSurface(screenSurface, NULL, self->surface, NULL);. Window is a pointer to SDL_Window and screenSurface is a pointer to SDL_Surface. Why didnt it throw a error during compilation?? Ok, error is gone. But nothing displays.

EDIT no. 2 I found it. It was such a stupid mistake. This is the right solution: SDL_BlitSurface(self->surface, NULL, screenSurface, NULL); Here is how SDL_BlitSurface looks like:

int SDL_BlitSurface(SDL_Surface*    src,
                const SDL_Rect* srcrect,
                SDL_Surface*    dst,
                SDL_Rect*       dstrect)

First has to be a source surface and third destination surface. It was written conversely. It caused a bug.

Pruky
  • 11
  • 3
  • Well... I might find that bug. SDL_BlitSurface(window ....) There should be SDL_Surface instead of window which is pointer to SDL_Window. Error is gone but nothing still displays. – Pruky Aug 02 '16 at 10:25
  • Passing wrong pointer type would issue a warning, not an error. If you didn't suppressed warnings you probably overlooked it. `-Werror` flag can instruct gcc to treat all produced warnings as errors (i.e. stop compilation and return failure). – keltar Aug 02 '16 at 12:48
  • @keltar Thank you! :) – Pruky Aug 02 '16 at 13:37

0 Answers0