我试图在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
我不明白为什么在draw_player函数中self->surface->locked
为NULL。表面上的指针是相同的,所以...我真的不明白。
我没有在我的代码中的任何地方调用SDL_LockSurface,但SDL抱怨表面在blit期间被锁定 - Surfaces must not be locked during blit
。我试图在SDL_BlitSurface之前调用SDL_UnlockSurface但没有任何改变。有任何想法吗?我必须注意到我在C和SDL中更好。
我运行Fedora 24.由于SDL是跨平台的lib,它应该不是问题。
我使用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。由于结果相同,我认为我的编码风格不是问题。但我可能错了。随意纠正我。
编辑:
我可能会发现这个bug。 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)
首先必须是源表面和第三个目标表面。反过来写的。它造成了一个错误。