SDL Window 只渲染后面的内容

SDL Window only renders contents behind it

我有以下 Pascal 代码,使用标准 SDL2 库。所有的代码都是有效的,图像在正确的目录中,并且在极少数情况下会加载所需的图像。然而,在 99% 的情况下,它只显示其背后 window 内容的静态图片。

program project1;

{$mode objfpc}{$H+}

uses
    {$IFDEF UNIX}{$IFDEF UseCThreads}
    cthreads,
    {$ENDIF}{$ENDIF}
    Classes, sysutils, SDL2, SDL2_image
    { you can add units after this };

const
  SWIDTH = 709;
  SHEIGHT = 488;
var
  Window: PSDL_Window;
  ScreenSurface, Symbol: PSDL_Surface;
begin
  WriteLn(GetCurrentDir);
  if SDL_Init(SDL_INIT_VIDEO) < 0 then halt;
  SDL_Init(SDL_INIT_EVERYTHING);
  Window:= SDL_CreateWindow('Symbol Test', SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SWIDTH, SHEIGHT, SDL_WINDOW_SHOWN);
    ScreenSurface:= SDL_GetWindowSurface(Window);
  IMG_Init(IMG_INIT_PNG);
    Symbol:= IMG_Load('symbol.png');
  SDL_BlitSurface(Symbol, nil, ScreenSurface, nil);
  SDL_UpdateWindowSurface(Window);
  SDL_Delay(5000);
    SDL_FreeSurface(Symbol);
  SDL_FreeSurface(ScreenSurface);

  SDL_DestroyWindow(Window);
  SDL_Quit();
end.

感谢 keltar 在评论中指出这是与 VSync 相关的错误。通过将更新过程转移到事件队列内部完成,而不是在延迟之前静态地完成一次,一切正常。这是更新后的代码供参考:

program project1;

{$mode tp}{$H+}

uses
    {$IFDEF UNIX}{$IFDEF UseCThreads}
    cthreads,
    {$ENDIF}{$ENDIF}
    Classes, sysutils, SDL2, SDL2_image
    { you can add units after this };

const
  SWIDTH = 709;
  SHEIGHT = 488;
var
  Window: PSDL_Window;
  ScreenSurface, Symbol: PSDL_Surface;
  e: TSDL_Event;
begin
  WriteLn(GetCurrentDir);
  if SDL_Init(SDL_INIT_VIDEO) < 0 then halt;
  SDL_Init(SDL_INIT_EVERYTHING);
  Window:= SDL_CreateWindow('Symbol Test', SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SWIDTH, SHEIGHT, SDL_WINDOW_SHOWN);
    ScreenSurface:= SDL_GetWindowSurface(Window);
  IMG_Init(IMG_INIT_PNG);
    Symbol:= IMG_Load('symbol.png');
  SDL_BlitSurface(Symbol, nil, ScreenSurface, nil);
  while true do
  begin
    while SDL_PollEvent(@e) <> 0 do
    begin
      if e.type_ = SDL_KEYDOWN then WriteLn(e.key.keysym.scancode);
      SDL_UpdateWindowSurface(Window);
    end;
  end;

  SDL_DestroyWindow(Window);
  SDL_Quit();
end.