我正在研究2D视频游戏框架,我之前从未编写过游戏循环。我曾经研究过的大多数框架似乎都实现了draw
和update
方法。
对于my project,我实现了一个调用这两种方法的循环。我注意到其他框架,这些方法并不总是被称为交替。某些框架的update
运行速度超过draw
。此外,大多数这些类型的框架将以60FPS运行。我想我在这里需要一些睡眠。
我的问题是,实现这种类型循环的最佳方法是什么?我打电话给draw
然后update
,反之亦然?在我的情况下,我正在编写SDL2的包装器,所以也许该库需要以某种方式设置某些东西?
这是我正在考虑实施的一些“伪”代码。
loop do
clear_screen
draw
update
sleep(16.milliseconds)
break if window_is_closed
end
虽然我的项目是用Crystal-Lang编写的,但我更多的是寻找可应用于任何语言的一般概念。
答案 0 :(得分:2)
这取决于你想要达到的目标。有些游戏更喜欢游戏逻辑比帧速率更频繁地运行(我相信源游戏会这样做),对于某些游戏,你可能希望游戏逻辑运行频率较低(我能想到的唯一例子是服务器)一些多人游戏,非常着名的Overwatch)。
同样重要的是要考虑这是分辨率的问题,而不是速度问题。逻辑速率为120且帧速率为60的游戏不一定以x2速度运行,任何时候游戏逻辑中的关键操作都应该相对于时钟*而不是抽动率进行,否则你的游戏将逐渐进入慢速运动状态。帧渲染时间太长。
我建议写一个这样的循环:
loop do
time_until_update = (update_interval + time_of_last_update) - current_time
time_until_draw = (draw_interval + time_of_last_draw) - current_time
work_done = false
# Update the game if it's been enough time
if time_until_update <= 0
update
time_of_last_update = current_time
work_done = true
end
# Draw the screen if it's been enough time
if time_until_draw <= 0
clear_screen
draw
time_of_last_draw = current_time
work_done = true
end
# Nothing to do, sleep for the smallest period
if work_done == false
smaller = time_until_update
if time_until_draw < smaller
smaller = time_until_draw
end
sleep_for(smaller)
end
# Leave, maybe
break if window_is_closed
end
你不想每帧等待16毫秒,否则如果帧花费了很多时间来完成,你最终可能会过度等待。 work_done
变量是这样的,我们知道我们在循环开始时计算的间隔是否仍然有效,我们可能已经完成了5ms的工作,这会使我们的睡眠完全关闭,所以在这种情况下我们去回来并计算新的价值。
*你可能想要对时钟进行抽象化,直接使用时钟可以产生一些奇怪的效果,例如如果你保存游戏而你上次使用神奇的力量作为时钟时间保存,它会立即脱落加载保存时的冷却时间,因为现在是过去几分钟,几小时甚至几天。操作系统暂停进程也存在类似问题。