javascript 如何重置three.js时钟?

66bbxpm5  于 2023-01-16  发布在  Java
关注(0)|答案(4)|浏览(226)

我想重置时钟,以便clock.getElapsedTime()从我重置时钟时起给我一个新的时间(例如,在第二次重新启动游戏关卡/场景时很有用)。
我在init()中初始化clock = new THREE.Clock();,在我的游戏循环update()中,我使用这个时钟。但是当游戏结束时,我想重置时钟(我不会再次初始化关卡,只是将玩家定位回起点,所以我不会初始化新的时钟)。
我怎样才能做到这一点?

wnavrhmk

wnavrhmk1#

坏消息:从2015年10月发布的r73开始,不可能THREE.Clock重置为零时间。解释如下,唯一可能的解决方案在此答案的末尾。
三钟设计中的问题深入探讨
时钟的设计是危险的...

  • -- Mrdoob,GitHub问题评论 *

要了解THREE.Clock中的缺陷,我们必须检查the source code,看看它是如何工作的。我们可以看到,在时钟的构造函数中,一些变量被示例化,乍一看,我们可以覆盖我们的Clock示例,将其重置为零:

this.startTime = 0;
this.oldTime = 0;
this.elapsedTime = 0;

但是,如果再深入一点,我们需要弄清楚当getElapsedTime()被调用时会发生什么,在幕后,它调用getDelta()getDelta()会变异为this.elapsedTime,也就是getDelta and getElapsedTime are dangerous, conflicting functions,但是我们仍然需要更仔细地研究getDelta

var newTime = self.performance.now();

diff = 0.001 * ( newTime - this.oldTime );
this.oldTime = newTime;
this.elapsedTime += diff;

这个函数**引用了某个未知的隐式全局变量self,**并调用了某个奇怪的函数self.performance.now()。危险信号!但是让我们继续挖掘...
结果是Three在“main”Three.js文件中定义了一个全局变量self,它的属性为performance,方法为now()
回到THREE.Clock,看看它是如何计算this.elapsedTime的,它基于self.performance.now()返回的值,表面上看起来很简单,但真正的问题出现在这里,我们可以看到self.performance.now()在闭包中创建了一个真正的“私有”变量,这意味着外部世界的任何人都不能看到/访问它:

( function () {
    var start = Date.now();
    self.performance.now = function () {
        return Date.now() - start;
    }
} )();

start变量是应用程序的开始时间,从Date.now()返回,以毫秒为单位。
这意味着**当Three.js库加载时,start将被设置为值Date.now()。**为了澄清,简单地包含Three.js脚本对计时器具有全局的、不可逆的副作用。回顾一下时钟,我们可以看到self.performance.now()的返回值用于计算Clock的当前经过时间。因为这是基于Three.js的私有的、不可访问的“开始时间”,它将始终相对于您包含Three.js脚本的时间。

变通方案#1

在你的游戏/关卡开始时存储startTime = clock.getElapsedTime(),并相对于此进行所有的计算。类似var currentTime = clock.getElapsedTime() - startTime的东西是从你的场景加载/开始获得真实绝对时间的唯一方法。

变通方案2

Three.Clock实际上只是Date.now()的一个薄薄的 Package 器,Date.now()是一个IE9+可用的方法。您最好围绕它创建自己的小抽象来获得一个合理的时钟,并使用一个易于实现的reset()方法。如果我找到一个具有此功能的npm包,或者自己创建一个,我会更新此答案。

变通方案3

等待Three.js Three.Clock源代码更新,可能由我来更新。由于有一个开放的票证,修复它的拉取请求可能会被接受。

puruo6ea

puruo6ea2#

保存游戏开始时的时间:var gameStartTime = clock.performance.now(),并且通过在游戏期间的任何其他点(包括其结束)从clock.performance.now()减去gameStartTime来计算此后的运行时间。gameStartTime - gameStartTime将等于零,clock.performance.now() - gameStartTime将为您提供自游戏开始以来的秒数或分钟数。
下面是对JavaScript中performance.now()定时器函数的引用。

brvekthn

brvekthn3#

这不会重置时钟,但会生成一个新的时钟对象,并每隔5秒将新值赋给lapsedTime变量:

let clock = new THREE.Clock();

const animate = () => {
  let elapsedTime = clock.getElapsedTime();
  if (elapsedTime > 5) {
    clock = new THREE.Clock();
  }
  window.requestAnimationFrame(animate);
};
oogrdqng

oogrdqng4#

下面是我使用startpausereset作为动画系统运行时的简单解决方案。

let offsetTime = 0; // in milliseconds

let start = false;

function reset() {

    offsetTime = 0;    

    start = false;

}

function start() {
    
    if ( start ) return;

    offsetTime += performance.now();    

    start = true;

}

function pause() {
    
    if ( start ) return;

    offsetTime -= performance.now();    

    start = false;

}

const animationRuntime = performance.now() - offsetTime;

相关问题