0

我一直在尝试用 HTML5/JS 制作一个简单的游戏。我已经设法为状态机和游戏循环准备了一个基本骨架,但即使是做一个简单的矩形移动也会导致一些“有形”的波动。

更重要的是,在让它闲置一段时间(跳出)之后,它似乎滴答作响的速度非常快,使一个简单的按键移动矩形远远超过它应该。

我正在使用setTimeout游戏的更新。在每个“滴答”期间,我调用当前状态的更新函数,即

State.prototype.update = function(ms) {
    this.ticks += ms;

    var updates = 0;
    while(this.ticks >= State.DELTA_TIME && updates < State.MAX_UPDATES) {
          this.updateState();

          this.updateFrameTicks += State.DELTA_TIME;
          this.updateFrames++;

          if(this.updateFrameTicks >= 1000) {
              this.ups = this.updateFrames;
              this.updateFrames = 0;
              this.updateFrameTicks -= 1000;
          }

        this.ticks -= State.DELTA_TIME;
        updates++;
    }   

    if(updates > 0) {
          this.renderFrameTicks += updates*State.DELTA_TIME;
          this.renderFrames++;

          if(this.renderFrameTicks >= 1000) {
              this.rps = this.renderFrames;
              this.renderFrames = 0;
              this.renderFrameTicks -= 1000;
          }

          this.renderState(updates*State.DELTA_TIME);
    }

};

这个想法是Game.update使用 尽可能频繁地调用setTimeout,然后将经过的时间传递给State.updateState.update仅当状态累积的时间大于或等于固定更新时间步长时才会更新状态。如果状态实际更新,State.update也会渲染/重绘当前状态,确保状态呈现与状态模拟相匹配。

现在,我知道这requestAnimationFrame比 更好setTimeout,但理论上当前版本应该可以工作,除非我犯了一个根本性错误。

这是我到目前为止所拥有的:http: //jsbin.com/ogicec/1编辑

您可以清楚地观察到它有断断续续的现象,如果您长时间观察并重新进入,它似乎比正常运行“更快”。

我无法真正确定问题所在,因此非常感谢您的帮助!

编辑: 我将状态的更新和渲染部分分开,setTimeout用于更新和requestAnimationFrame渲染。它解决了标签问题,整个事情感觉更加一致。但是,与此同时,性能仍然不稳定,我想在继续添加更多游戏相关代码之前确保它足够流畅。

这是更新的 JSBin:http: //jsbin.com/eyarod/1编辑

4

2 回答 2

1

在我的系统上,JSBin 测试实际上几乎一直使用 UPS: 60 和 FPS: 60 运行(注意我在 i7-2600k 上的 chrome 25.0.1349.2 dev 中运行它,并且我打开了 VSync,所以这是为什么帧率会受到限制)。当我切换到另一个选项卡并返回FPS时,请稍加干扰:我怀疑这与浏览器“ browsers stertimeout”调用的方式有关。

更一般地说,您似乎试图将消息轮询繁忙等待循环硬塞到 JavaScript 中,这是一种事件驱动的语言。我怀疑(但不确定),添加一个使用当前 x 和 y 更新共享对象的事件处理程序,然后有一个单独的循环以固定到监视器刷新率的速率更新屏幕会执行很多更好的。

于 2012-12-10T17:59:08.943 回答
0

现在,我知道 requestAnimationFrame 比 setTimeout 效果更好,但理论上当前版本应该可以工作,除非我犯了一个根本性的错误。

允许用户代理等待额外的时间,只要他们愿意,超过提供给的毫秒参数setTimeout(并且通常执行延迟执行的非实时 API 保证代码不会在您指定的延迟之前运行,但它可能会运行您指定的延迟后的任意时间)。此外,当一次更新调用this.ticks非常接近但小于一帧时,您可能会观察到不稳定的运动,而下一次调用发生在触发两次更新的时间,跳过一帧。

错误是setTimeout永远不能提供这样做的保证requestAnimationFrame

如果您使用 requestAnimationFrame 并继续遇到问题,您可以使用 Chrome 开发工具深入研究它们;这是有关避免动画斩波的幻灯片

于 2012-12-10T19:27:30.017 回答