Loops 使用OpenGL平滑相机移动
我已经使用自己的游戏引擎有一段时间了,我一直在尝试让输入和控制更像AAA FPS游戏,或者至少是一款像样的独立游戏。在过去的一期中,我发布了几个关于制作平滑相机的主题,在发布这些主题时,我对结果感到满意。但是现在,我觉得它不够平滑,我已经把整个引擎切换到SDL,所以我可以控制循环。(之前我使用的是GLUT)。将所有内容更改为SDL后,鼠标像黄油一样光滑,但相机的移动(行走)仍然口吃,看起来很糟糕。我已经实现了Dwitter的最后一个游戏循环,即带有插值的循环,下面是相关代码:Loops 使用OpenGL平滑相机移动,loops,opengl,camera,smooth,Loops,Opengl,Camera,Smooth,我已经使用自己的游戏引擎有一段时间了,我一直在尝试让输入和控制更像AAA FPS游戏,或者至少是一款像样的独立游戏。在过去的一期中,我发布了几个关于制作平滑相机的主题,在发布这些主题时,我对结果感到满意。但是现在,我觉得它不够平滑,我已经把整个引擎切换到SDL,所以我可以控制循环。(之前我使用的是GLUT)。将所有内容更改为SDL后,鼠标像黄油一样光滑,但相机的移动(行走)仍然口吃,看起来很糟糕。我已经实现了Dwitter的最后一个游戏循环,即带有插值的循环,下面是相关代码: int main
int main (int argc, char** argv)
{
arg1 = argc;
arg2 = argv;
engineInit();
//the loop has to stay here
//kill all extra threads so they don't cause problems after we quit
//gameloop
SDL_Event event;
bool running = true;
const int TPS = 20;
const int SKIP_TICKS = 1000 / TPS;
const int MAX_FRAMESKIP = 5;
int loops;
long lastSec = 0;
long nextGameTick = SDL_GetTicks();
while (running)
{
while (SDL_PollEvent(&event)) {
//do crap with events
switch (event.type)
{
int x,y,button;
case SDL_QUIT:
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_Quit();
cout << "The window has been closed.\n";
running = false;
break;
case SDL_MOUSEMOTION:
SDL_GetMouseState(&x, &y);
passiveMouse(x,y);
break;
case SDL_MOUSEBUTTONDOWN :
button = SDL_GetMouseState(&x, &y);
mouseFunc(button,1,x,y);
break;
case SDL_KEYDOWN:
keyboardDownFunc(event.key.keysym.sym);
break;
case SDL_KEYUP:
keyboardUpFunc(event.key.keysym.sym);
break;
default:
break;
}
}
loops = 0;
while (SDL_GetTicks()> nextGameTick && loops < MAX_FRAMESKIP) {
nextGameTick+=SKIP_TICKS;
loops++;
TickHandler.tps++;
TickHandler.onTick();
int tickTime = int(SDL_GetTicks()/1000);
if (tickTime > lastSec+1)
{
TickHandler.tps = 0;
lastSec = tickTime;
}
}
TickHandler.interpolation = double(SDL_GetTicks() + SKIP_TICKS - nextGameTick )
/ double( SKIP_TICKS );
TickHandler.onRender();
render();
}
Console.consoleActivated = false;
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
这是移动摄像机第一人称:
void inputs::moveCameraFirstPerson(float speed)
{
speed = speed*walkspeed;
float radx = ((yaw+addedAngle)*MPI/180);
camx -= (sinf(radx)/10)*speed;
camz += (cosf(radx)/10)*speed;
Physics.pos1 = -camx;
Physics.pos2 = -camz;
if (Physics.collided == true)
{float radx = ((yaw+Input.addedAngle)*3.1415926535/180);
camx += (sinf(radx)/20)*speed;
camz -= (cosf(radx)/20)*speed;
Physics.collided = false;
}
Client.x = camx;
Client.z = camz;
Client.y = camy;
Projectile.x = camx;
Projectile.z = camz;
}
如果我能把这些都整理好,有什么帮助或参考吗?你的问题是什么?如果您要求查看代码,则会有一个专门的StackExchange子网站。@datenwolf我只是想知道我对代码做了哪些错误,从而导致它这样做。它以每秒20拍的速度运行,也有60帧。更改tps似乎没有效果。虽然您的代码不太可能太复杂,以至于调用
SDL_GetTicks(…)
之间的时间不超过1毫秒,但在本例中,反复调用计时器的勾号函数是不好的。通常情况下,在帧的开头有一个勾选的时间,并在任何地方使用该值,以确保游戏逻辑发生的顺序不会影响技术上应该同时发生的事情。当你使用更高分辨率的定时器(SDL有一个1毫秒的定时器,其他框架可以让你得到10纳秒或更少)时,这会成为一个更严重的问题。@AndonM.Coleman我更改了代码,虽然这是有意义的,但来自游戏循环的引用并没有做到这一点。然而,这并不能解决口吃问题。
void inputs::moveCameraFirstPerson(float speed)
{
speed = speed*walkspeed;
float radx = ((yaw+addedAngle)*MPI/180);
camx -= (sinf(radx)/10)*speed;
camz += (cosf(radx)/10)*speed;
Physics.pos1 = -camx;
Physics.pos2 = -camz;
if (Physics.collided == true)
{float radx = ((yaw+Input.addedAngle)*3.1415926535/180);
camx += (sinf(radx)/20)*speed;
camz -= (cosf(radx)/20)*speed;
Physics.collided = false;
}
Client.x = camx;
Client.z = camz;
Client.y = camy;
Projectile.x = camx;
Projectile.z = camz;
}