【问题标题】:SDL Window only renders contents behind itSDL Window 仅在其后面呈现内容
【发布时间】:2015-10-19 16:51:04
【问题描述】:

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

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.

【问题讨论】:

  • 可能与垂直同步有关。尝试循环显示多次直到 5 秒过去,或者禁用加速 (SDL_HINT_FRAMEBUFFER_ACCELERATION)。你也不应该释放ScreenSurface,但这与你的问题无关。 stackoverflow.com/questions/32500491/… 如果您使用启用了组合的 OS/WM 可能会有所帮助,尽管它没有提供明确的解决方案。
  • @keltar:太棒了!你是对的,这是垂直同步的问题。我现在已经修复了它,并且在轮询事件循环内进行更新是我所要做的。非常感谢!

标签: opengl sdl-2 freepascal lazarus


【解决方案1】:

感谢 cmets 中的 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.

【讨论】:

    猜你喜欢
    • 2012-12-02
    • 2015-11-24
    • 2015-09-12
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    相关资源
    最近更新 更多