这是我学习 SDL 的一系列文章中的一段代码:
double image_x = 0.0;
SDL_Rect image_position;
main () {
// Code to load a BMP file
// and blit the corresponding image-surface onto the window-surface
// with the destination position on window-surface defined by image_position.
while (game_is_running) { // Game loop
while (event_present) { // Event loop
// Logic
}
update(1.0/60.0);
}
}
void update (double delta_time) {
image_x = image_x + (5 * delta_time);
image_position.x = image_x;
draw();
}
为了更好地了解上下文,在特定教程中,作者解释了如何加载 BMP 文件,然后将其 blit 到窗口表面。然后,我们对图像进行动画处理,使其在屏幕上移动,但我们希望以受控的方式进行。
image_position
是一个简单的 SDL_Rect
,它将定义图像在窗口表面上的放置位置。当绘制到屏幕时,它将用作 SDL_BlitSurface 的最后一个参数,如下所示:
SDL_BlitSurface(image_surface, NULL, window_surface, &image_position);
函数
draw
(代码中未显示)应该清除屏幕并在屏幕上按image_position
指定的X和Y绘制图像。
函数
update
应该更新图像的位置,然后更新屏幕。
我的问题:
在文章中,作者指出将
1.0/60.0
传递给函数 update
将帧速率限制为 60fps。
根据代码,我认为这是错误的。
update
函数仅每 60 帧左右增加图像的 x 位置。这与每秒帧数不同,因为在 FPS 中涉及时间元素,而在 update
函数中不涉及时间。那么,作者的说法真的正确吗?或者我对代码的理解是否正确?
对本系列文章感兴趣的人:https://dev.to/noah11012/using-sdl2-scaling-and-moving-an-image-pj
注意:这篇文章只是为了验证我对代码的理解。这篇文章无意以任何方式损害原作者的声誉。
update (double delta_time)
应该用自上次绘制屏幕以来经过的时间来调用。
然后,image_x = image_x + (5 * delta_time);
将使 image_x
在较慢的机器上比在较快的机器上增加更多。
当您使用硬编码值调用它时,例如
1.0 / 60.0
,您实际上取消了使用此类函数的全部目的。
你应该做的是这样的:
double prev_time = get_time_as_double();
while (game_is_running) { // Game loop
while (event_present) { // Event loop
// Logic
}
double new_time = get_time_as_double();
update(new_time - prev_time);
prev_time = new_time;
}
get_time_as_double()
可以通过在Posix系统上调用clock_gettime
来实现。如果您使用非 Posix 操作系统,请找到一个能够提供具有相当高分辨率的稳定时钟的功能。
示例:
double get_time_as_double() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec + ts.tv_nsec / 1000000000.0;
}