gpt4 book ai didi

c++ - SDL2 硬件渲染的奇怪行为

转载 作者:搜寻专家 更新时间:2023-10-31 00:27:23 25 4
gpt4 key购买 nike

我想制作我的第一款游戏。
没什么特别的,只是蓝色矩形在按下 WSAD 键时移动。

问题是当我运行我的游戏时,矩形出现错误(见下图)。错误仅在水平移动时出现,而不会在垂直移动时出现。

enter image description here

这很有趣,当我换行时:

renderer = SDL_CreateRenderer(display, -1, SDL_RENDERER_ACCELERATED)

到:

renderer = SDL_CreateRenderer(display, -1, SDL_RENDERER_SOFTWARE)

一切正常

我正在使用 Windows 10、带 CMake(C++14) 的 MinGw 和 SDL 2.0.8、第七代英特尔酷睿 i5、Radeon M7 R465

我的代码 OnRender 函数负责渲染,也许我在其中做错了什么?(问题末尾发布的代码中的函数)

我还使用 SDL_WINDOW_OPENGL 标志来创建我的窗口,但将其更改为 SDL_WINDOW_SHOWN 不会改变任何内容。

#include <SDL2/SDL.h>

class Game
{
private:
SDL_Surface *display_surf = nullptr;
SDL_Renderer *renderer = nullptr;
SDL_Window *display = nullptr;

private:
bool running, prW = false, prS = false, prD = false, prA = false;
int x, y;
int spd_y, spd_x;
int scr_w, scr_h;

public:
Game();
int OnExecute();

public:
bool OnInit();
void OnEvent( SDL_Event *event );
void OnLoop();
void OnRender();
void OnCleanup();
};

Game::Game()
{
running = false;
}

int Game::OnExecute()
{
if( !OnInit() )
{
return -1;
}

running = true;
SDL_Event event;
while( running )
{
while( SDL_PollEvent( &event ) )
{
OnEvent( &event );
}

OnLoop();
OnRender();
SDL_Delay( 1 );
}

OnCleanup();
return 0;
}

bool Game::OnInit()
{
if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
{
return false;
}

SDL_DisplayMode dspm;
if( SDL_GetDesktopDisplayMode( 0, &dspm ) < 0 )
{
return false;
}

scr_h = dspm.h;
scr_w = dspm.w;

if( ( display = SDL_CreateWindow( "Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1920, 1080,
SDL_WINDOW_OPENGL ) ) == nullptr )
{
return false;
}

display_surf = SDL_GetWindowSurface( display );


if( ( renderer = SDL_CreateRenderer( display, -1, SDL_RENDERER_ACCELERATED ) ) == nullptr )
{
return false;
}

x = 0;
y = 0;

spd_x = 0;
spd_y = 0;

SDL_SetWindowFullscreen( display, SDL_WINDOW_FULLSCREEN );

return true;

}

void Game::OnEvent( SDL_Event *event )
{
if( event->type == SDL_QUIT )
{
running = false;
return;
}

switch( event->type )
{
case SDL_KEYDOWN:
switch( event->key.keysym.sym )
{
case SDLK_w:
if( prS )
{
spd_y = 0;
}
else
{
spd_y = -5;
}
prW = true;
break;
case SDLK_s:
if( prW )
{
spd_y = 0;
}
else
{
spd_y = 5;
}
prS = true;
break;
case SDLK_d:
if( prA )
{
spd_x = 0;
}
else
{
spd_x = 5;
}
prD = true;
break;
case SDLK_a:
if( prD )
{
spd_x = 0;
}
else
{
spd_x = -5;
}
prA = true;
break;
default:
return;
}

break;
case SDL_KEYUP:
switch( event->key.keysym.sym )
{
case SDLK_w:
if( !prS )
{
spd_y = 0;
}
else
{
spd_y = 5;
}
prW = false;
break;
case SDLK_s:
if( !prW )
{
spd_y = 0;
}
else
{
spd_y = -5;
}
prS = false;
break;
case SDLK_a:
if( !prD )
{
spd_x = 0;
}
else
{
spd_x = 5;
}
prA = false;
break;
case SDLK_d:
if( !prA )
{
spd_x = 0;
}
else
{
spd_x = -5;
}
prD = false;
break;
default:
return;
}
default:
return;
}
}

void Game::OnLoop()
{
x += spd_x;
y += spd_y;

if( x < 0 )
{
x = 0;
}
else if( x > scr_w - 100 )
{
x = scr_w - 100;
}

if( y < 0 )
{
y = 0;
}
else if( y > scr_h - 100 )
{
y = scr_h - 100;
}
}

void Game::OnRender()
{
SDL_SetRenderDrawColor( renderer, 0, 0, 0, 0x00 );

SDL_RenderClear( renderer );

SDL_Rect charc;
charc.x = x;
charc.y = y;
charc.w = 100;
charc.h = 100;

SDL_SetRenderDrawColor( renderer, 0, 0, 0xff, 0 );

SDL_RenderFillRect( renderer, &charc );

SDL_RenderPresent( renderer );
}

void Game::OnCleanup()
{
SDL_DestroyWindow( display );
SDL_Quit();
}

int main( int argc, char** argv )
{
Game game;
return game.OnExecute();
}

最佳答案

看起来很像tearing由高帧率和缺乏垂直同步引起。

我可以通过传递 SDL_RENDERER_ACCELERATED | 获得无泪绘图SDL_RENDERER_PRESENTVSYNCSDL_CreateRenderer() 上的标志:

#include <SDL2/SDL.h>
#include <iostream>

class Game
{
private:
SDL_Renderer *renderer = nullptr;
SDL_Window *display = nullptr;

private:
bool running, prW = false, prS = false, prD = false, prA = false;
int x, y;
int spd_y, spd_x;
int scr_w, scr_h;

public:
Game();
int OnExecute();

public:
bool OnInit();
void OnEvent( SDL_Event *event );
void OnLoop();
void OnRender();
void OnCleanup();
};

Game::Game()
{
running = false;
}

int Game::OnExecute()
{
if( !OnInit() )
{
return -1;
}

running = true;
SDL_Event event;

Uint32 beg = SDL_GetTicks();
size_t frames = 0;
while( running )
{
while( SDL_PollEvent( &event ) )
{
OnEvent( &event );
}

OnLoop();
OnRender();

frames++;
Uint32 end = SDL_GetTicks();
if( end - beg > 1000 )
{
std::cout << "Frame time: " << ( end - beg ) / frames << " ms" << std::endl;
beg = end;
frames = 0;
}
}

OnCleanup();
return 0;
}

bool Game::OnInit()
{
if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
{
return false;
}

if( ( display = SDL_CreateWindow( "Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, 0 ) ) == nullptr )
{
return false;
}

scr_w = 1280;
scr_h = 720;

Uint32 rflags = SDL_RENDERER_ACCELERATED;
rflags |= SDL_RENDERER_PRESENTVSYNC;
if( ( renderer = SDL_CreateRenderer( display, -1, rflags ) ) == nullptr )
{
return false;
}

x = 0;
y = 0;

spd_x = 0;
spd_y = 0;

return true;
}

void Game::OnEvent( SDL_Event *event )
{
if( event->type == SDL_QUIT )
{
running = false;
return;
}

switch( event->type )
{
case SDL_KEYDOWN:
switch( event->key.keysym.sym )
{
case SDLK_w:
if( prS )
{
spd_y = 0;
}
else
{
spd_y = -5;
}
prW = true;
break;
case SDLK_s:
if( prW )
{
spd_y = 0;
}
else
{
spd_y = 5;
}
prS = true;
break;
case SDLK_d:
if( prA )
{
spd_x = 0;
}
else
{
spd_x = 5;
}
prD = true;
break;
case SDLK_a:
if( prD )
{
spd_x = 0;
}
else
{
spd_x = -5;
}
prA = true;
break;
default:
return;
}

break;
case SDL_KEYUP:
switch( event->key.keysym.sym )
{
case SDLK_w:
if( !prS )
{
spd_y = 0;
}
else
{
spd_y = 5;
}
prW = false;
break;
case SDLK_s:
if( !prW )
{
spd_y = 0;
}
else
{
spd_y = -5;
}
prS = false;
break;
case SDLK_a:
if( !prD )
{
spd_x = 0;
}
else
{
spd_x = 5;
}
prA = false;
break;
case SDLK_d:
if( !prA )
{
spd_x = 0;
}
else
{
spd_x = -5;
}
prD = false;
break;
default:
return;
}
default:
return;
}
}

void Game::OnLoop()
{
x += spd_x;
y += spd_y;

if( x < 0 )
{
x = 0;
}
else if( x > scr_w - 100 )
{
x = scr_w - 100;
}

if( y < 0 )
{
y = 0;
}
else if( y > scr_h - 100 )
{
y = scr_h - 100;
}
}

void Game::OnRender()
{
SDL_SetRenderDrawColor( renderer, 0, 0, 0, 0x00 );

SDL_RenderClear( renderer );

SDL_Rect charc;
charc.x = x;
charc.y = y;
charc.w = 100;
charc.h = 100;

SDL_SetRenderDrawColor( renderer, 0, 0, 0xff, 0 );

SDL_RenderFillRect( renderer, &charc );

SDL_Delay( 1 );
SDL_RenderPresent( renderer );
}

void Game::OnCleanup()
{
SDL_DestroyWindow( display );
SDL_Quit();
}

int main( int argc, char** argv )
{
Game game;
return game.OnExecute();
}

如果我只是通过 SDL_RENDERER_ACCELERATED,我会出现撕裂和大大更高的帧速率。

确保您的操作系统未配置为默认禁用垂直同步。

关于c++ - SDL2 硬件渲染的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49388918/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com