kri*_*key 5 javascript three.js
我想重置时钟,以便从重置时钟开始clock.getElapsedTime()给我一个新的时间(例如,第二次重启游戏关卡/场景时很有用).
我发起clock = new THREE.Clock(); 的init(),在我的游戏循环update()中,我使用这个时钟.但是当游戏结束时,我想重置时钟(我没有再次启动该级别,而只是将玩家放回到开头,所以我没有启动新的时钟).
我怎样才能做到这一点?
坏消息:从2015年10月发布的r73开始,无法重置THREE.Clock为零时间.解释如下,唯一可行的解决方法是在这个答案的最后.
时钟的设计很危险......
- Mrdoob,GitHub发表评论
要理解这些缺陷,THREE.Clock我们必须检查源代码以了解它是如何工作的.我们可以看到在Clock的构造函数中,实例化了一些变量,这些变量首先看起来像我们可以覆盖我们的Clock实例重置为零:
this.startTime = 0;
this.oldTime = 0;
this.elapsedTime = 0;
Run Code Online (Sandbox Code Playgroud)
但是,深入挖掘,我们需要弄清楚何时getElapsedTime()被调用.在引擎盖下,它调用getDelta(),它变异this.elapsedTime,这意味着getDelta并且getElapsedTime是危险的,冲突的函数,但我们仍然需要仔细观察getDelta:
var newTime = self.performance.now();
diff = 0.001 * ( newTime - this.oldTime );
this.oldTime = newTime;
this.elapsedTime += diff;
Run Code Online (Sandbox Code Playgroud)
这个函数引用一些未知的隐式全局变量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;
}
} )();
Run Code Online (Sandbox Code Playgroud)
此start变量是应用程序的开始时间,以毫秒为单位返回Date.now().
这意味着当Three.js库加载时,start将设置为该值Date.now().为了澄清,简单地包括Three.js脚本对于计时器具有全局的,不可逆的副作用.回顾时钟,我们可以看到返回值self.performance.now()用于计算当前经过的时间Clock.因为这是基于私有的,无法访问的"开始时间" Three.js,所以它总是与您包含Three.js脚本时相关.
存储startTime = clock.getElapsedTime()在您的游戏/关卡开始并进行相关的所有计算.这样的东西var currentTime = clock.getElapsedTime() - startTime是从场景加载/开始获得真正绝对时间的唯一方法.
Three.Clock引擎盖下真的只是一个薄的包装Date.now(),这是一个IE9 +可用的方法.你可能最好在这个周围创建自己的微小抽象,以获得一个理智的时钟,一个易于实现的reset()方法.如果我找到npm具有此功能的软件包,或者自己制作软件包,我将更新此答案.
等待Three.Clock可能由我更新Three.js 源代码.由于有一张开放票,因此可能会接受修复它的拉动请求.