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->lockeddraw_player 関数内が NULL である理由がわかりません。表面へのポインターは同じなので...よくわかりません。コードのどこにも SDL_LockSurface を呼び出していませんが、SDL はブリット中にサーフェスがロックされていると不平を言っていSurfaces must not be locked during blitます。SDL_BlitSurface の前に SDL_UnlockSurface を呼び出そうとしましたが、何も変わりませんでした。何か案は?私は C と SDL の初心者です。Fedora 24 を実行しています。SDL はクロスプラットフォーム ライブラリであるため、問題にはなりません。gcc 6.1.1 を使用しています。
Player のスプライトは 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(...)。描画関数も同様です。少しハッキーなスタイルですが、気に入っています。早速 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)
1 番目がソース サーフェスで、3 番目が宛先サーフェスである必要があります。逆に書いてありました。バグを引き起こしました。