这个是我再次参考Game Progarmming Pattern - Game Loop这一章节,与Ralylib这个纯C的libary得到的一个结果。
之前想说设计是这样子:
while (true) {
StartScene();
// Input here
// Update here
BeginRendering();
// Render here
EndRendering();
EndScene();
}
然後把时间的处理放在StartScene()
与EndScene()
,但看了Game Programming Pattern之後发现,正常来说如果要限制FPS,达到Framerate Indepent的话,应该是只要对Update()
,也就是逻辑的地方做限制,但上面这个的设计是连Input()
跟Render()
都在里面了。後来在github上找到一个游戏libary - Raylib(没错!是当"抄"人的时候了),他的做法是这样
while (true) {
// Input here
// Update here
BeginDrawing();
// Render here
EndDrawing();
Raylib是把delta time称作frame time,是由update time跟render time合并起来的。
BeginDrawing()
呼叫时会计算update time然後储存;EndDrawing()
呼叫时,同理会更新render time。然後这两个相加,就是这一个frame的处理时间,再来就是一个重点了。
// in `BeginDrawing`
WINDOW.Time.current_time = (float)glfwGetTime();
WINDOW.Time.update_time = WINDOW.Time.current_time - WINDOW.Time.previous_time;
WINDOW.Time.previous_time = WINDOW.Time.current_time;
// in `EndDrawing`
WINDOW.Time.current_time = (float)glfwGetTime();
WINDOW.Time.render_time = WINDOW.Time.current_time - WINDOW.Time.previous_time;
WINDOW.Time.previous_time = WINDOW.Time.current_time;
WINDOW.Time.frame_time = WINDOW.Time.render_time + WINDOW.Time.update_time; // 这个就是delta time
如果要限制60 FPS,也就是约0.01666秒的时间,update time加上render time的时间可能会小於0.016666秒,於是可以用一些方法让game loop强制处理剩余的秒数。
Sleep
没错!让执行序强制停止N秒,没记错的话,SDL中的SDL_Delay
底下就是调用各名台相关的Sleep
while loop
我是用这一种方式,在EndDrawing()
那边接下去写来着:
if (WINDOW.Time.frame_time < WINDOW.Time.target_time) {
float wait_time = WINDOW.Time.target_time - WINDOW.Time.frame_time;
// wait time
float start_wait_time = glfwGetTime();
float end_wait_time = 0.0f;
while ((end_wait_time - start_wait_time) < wait_time) {
end_wait_time = glfwGetTime();
}
// add extra time
WINDOW.Time.current_time = (float)glfwGetTime();
float extra_time = WINDOW.Time.current_time - WINDOW.Time.previous_time;
WINDOW.Time.previous_time = WINDOW.Time.current_time;
WINDOW.Time.frame_time += extra_time;
}
昨天有提到Framerate Independent,来实验一下
在不同的FPS下,高FPS会有较低的delta time;低FPS的会有较高的delta time。故两者最後都会在同时间抵达目的地。
这边贴上,我简单测的code
SetTargetFPS(10); // change fps here!!
float current_time = GetTime();
float previous_time = GetTime();
float time_elapsed = 0.0f;
int test_count = 0;
// Game loop
while (IsWindowRunning()) {
if (e.pos.x > 800.0f) {
current_time = GetTime();
time_elapsed = current_time - previous_time;
previous_time = current_time;
LogInfo("Time elapsed: %f", time_elapsed);
e.pos.x = 0.0f;
}
e.pos = V2fAdd(e.pos, V2fScalef(e.speed, GetDeltaTime()));
StartScene(COLOR_BLACK);
BeginRendering();
DrawRectangle(e.pos, size, 0.0f, e.c);
EndRendering();
EndScene();
}
有了delta time的调节,不管是10 FPS还是144 FPS都会在同个(会有0.0几的误差...)时间,从左走到右。如果没有个话,就会是全看CPU的频率在表现跟处理了。
备注: raylib作者还有在更新,我贴的是在00a763e
的这个版本
>>: IOS、Python自学心得30天 Day-20 .h5 to .tflite to .mlmodel
打Code打Call | 主控台App | Hello World 🐄点此填写今日份随堂测验 ...
-数位签章 使用您的私钥加密代码的指纹或对代码进行散列并使用您的私钥加密结果是生成数字签名的 改写...
Today mobile technology has become so advanced tha...
今天我们把这个App完成~ 首先,先到我们的Main.storyboard 点击右上角 + ->...
说到学习资源,最容易学习的方式就是从母语开始 中文文章 Jerry Hong 的部落格 Jerry ...