1

我正在尝试用 C 编写一个简单的游戏。我使用 SDL2 来绘制东西。这是一个主循环:

...
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;
}
...

这是draw_player函数:

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);
}

它编译良好,但运行后不显示播放器。输出:

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

我不明白为什么self->surface->locked在 draw_player 函数中是 NULL。指向表面的指针是相同的,所以......我真的不明白。我没有在我的代码中的任何地方调用 SDL_LockSurface 但 SDL 抱怨表面在 blit - 期间被锁定Surfaces must not be locked during blit。我试图在 SDL_BlitSurface 之前调用 SDL_UnlockSurface 但没有任何改变。有任何想法吗?我必须注意,我是 C 和 SDL 的初学者。我运行 Fedora 24。因为 SDL 是跨平台库,所以应该不是问题。我使用 gcc 6.1.1。

玩家的精灵是 png 格式,这就是我使用 IMG_Load 的原因。以下是播放器的创建方式:

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
}

最后我要告诉你的。我在 GameObject 结构中存储指向绘制和更新函数的指针。所以我把 update_player 称为player->update(...). 绘图函数也是如此。这是一个有点hacky的风格,但我喜欢它。我试图马上打电话给 draw_player。由于结果相同,我认为我的编码风格不是问题。但我可能错了。随时纠正我。

编辑:我可能会发现那个错误。SDL_BlitSurface(window, NULL, self->surface, NULL);应该是SDL_BlitSurface(screenSurface, NULL, self->surface, NULL);。Window 是指向 SDL_Window 的指针,而 screenSurface 是指向 SDL_Surface 的指针。为什么编译的时候没有报错??好的,错误消失了。但没有任何显示。

编辑号 2 我找到了。这是一个愚蠢的错误。这是正确的解决方案:SDL_BlitSurface(self->surface, NULL, screenSurface, NULL); SDL_BlitSurface 如下所示:

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

首先必须是源表面和第三目标表面。是反过来写的。它导致了一个错误。

4

0 回答 0