【发布时间】:2018-03-20 16:02:30
【问题描述】:
我想创建我的第一个游戏。
没什么特别的,只是按下 WSAD 键时蓝色矩形移动。
问题是当我运行我的游戏时,矩形存在错误(见下图)。错误仅在水平移动时出现,而不是垂直移动。
有趣的是,当我换行时:
renderer = SDL_CreateRenderer(display, -1, SDL_RENDERER_ACCELERATED)
到:
renderer = SDL_CreateRenderer(display, -1, SDL_RENDERER_SOFTWARE)
一切正常
我正在使用 Windows 10、MinGw 和 CMake(C++14) 和 SDL 2.0.8、英特尔酷睿 i5 第 7 代、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();
}
【问题讨论】:
-
你的主循环是什么样的?您也可以尝试将 SDL_RENDER_PRESENTVSYNC 添加到您的渲染器初始化函数中。
-
@Aram 刚刚发布了我的代码
-
@genpfault 刚刚发布了我的代码。我知道它必须是“最小的”,但我不确定在这种情况下“最小”是什么,所以我刚刚发布了所有代码。时间不长。
-
尝试在 onRender 之后添加几毫秒的睡眠,std::this_thread::sleep_for(std::chrono::milliseconds(5));包括chrono和thread。看看会发生什么。
-
如果你点击了给你的链接,你会知道在这种情况下“最小”是什么。 MCVE 不是建议。这是一个要求。您应该已经创建了一个作为您自己调试的一部分!