Java实现支持运行时调整帧率上限且不影响update逻辑速度的游戏循环
核心实现思路
你需要将**逻辑更新(update)和画面渲染(render)**的计时逻辑完全解耦:逻辑更新采用固定时间步长执行,不受渲染帧率上限调整的影响,仅渲染环节单独做帧率上限控制。
具体实现步骤
- 预先定义固定的逻辑更新间隔,比如要求每秒固定执行60次update,就定义常量:
long FIXED_UPDATE_STEP = 1000_000_000L / 60;(单位为纳秒,计时精度更高),该值全程固定不随渲染帧率配置修改。 - 维护独立的逻辑更新时间累加器:每次游戏循环先计算当前帧与上一帧的时间差,将时间差累加到累加器变量中;只要累加器数值大于等于
FIXED_UPDATE_STEP,就执行一次update(),并将累加器减去FIXED_UPDATE_STEP,直到累加器不足一个步长为止。 - 渲染环节单独做帧率限制:仅在渲染前根据当前设置的渲染帧率上限计算需要等待的时间,动态调整帧率上限时仅修改渲染环节的等待阈值即可,完全不接触逻辑更新的计时逻辑。
- 可选优化:可以将累加器剩余的不足一个步长的时间作为插值参数传给
render()方法,用于画面帧插值,避免高帧率下画面卡顿。
Java代码示例
public class GameLoop implements Runnable { // 固定逻辑更新率:每秒60次 private static final long FIXED_UPDATE_STEP = 1000_000_000L / 60; // 渲染帧率上限,支持运行时动态修改 private volatile int renderFpsCap = 60; @Override public void run() { long lastTickTime = System.nanoTime(); long accumulator = 0; while (isRunning()) { long currentTime = System.nanoTime(); long frameDelta = currentTime - lastTickTime; lastTickTime = currentTime; accumulator += frameDelta; // 逻辑更新:固定步长,不受渲染帧率影响 while (accumulator >= FIXED_UPDATE_STEP) { update(); accumulator -= FIXED_UPDATE_STEP; } // 计算插值参数,可选传入render实现平滑渲染 float interpolation = (float) (accumulator / (double) FIXED_UPDATE_STEP); render(interpolation); // 仅渲染环节做帧率限制 long renderInterval = 1000_000_000L / renderFpsCap; long renderCost = System.nanoTime() - currentTime; if (renderCost < renderInterval) { try { long sleepMs = (renderInterval - renderCost) / 1000_000L; int sleepNano = (int) ((renderInterval - renderCost) % 1000_000L); Thread.sleep(sleepMs, sleepNano); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } } // 运行时动态调整渲染帧率上限的入口,完全不影响逻辑更新速度 public void setRenderFpsCap(int renderFpsCap) { this.renderFpsCap = Math.max(1, renderFpsCap); } private boolean isRunning() { // 游戏运行状态判断逻辑 return true; } private void update() { // 游戏逻辑更新代码 } private void render(float interpolation) { // 画面渲染代码 } }
内容的提问来源于stack exchange,提问作者user13351174
相关产品推荐
相关产品推荐

