如何重置三.js时钟
How to reset three.js clock?
我想重置时钟,以便clock.getElapsedTime()
从重置时钟时开始给我一个新的时间(例如,在第二次重新启动游戏关卡/场景时很有用)。
我在init()
启动clock = new THREE.Clock();
,在我的游戏循环update()
中,我正在使用这个时钟。但是当游戏结束时,我想重置时钟(我没有再次启动关卡,只是将玩家定位回起点,所以我不会启动新的时钟)。
我怎样才能做到这一点?
坏消息:从 2015 年 10 月发布的 r73 开始,不可能将THREE.Clock
重置为零时间。解释如下,唯一可能的解决方法是本答案的末尾。
深入探讨三时钟设计存在的问题
时钟的设计很危险...
——Mrdoob,GitHub问题评论
要了解THREE.Clock
中的缺陷,我们必须检查源代码以了解其工作原理。我们可以看到,在 Clock 的构造函数中,实例化了一些变量,乍一看,我们可以覆盖Clock
实例以重置为零:
this.startTime = 0;
this.oldTime = 0;
this.elapsedTime = 0;
但是,深入挖掘,我们需要弄清楚调用getElapsedTime()
时会发生什么。在引擎盖下,它调用getDelta()
,它变异this.elapsedTime
,这意味着getDelta
和getElapsedTime
是危险的、冲突的函数,但我们仍然需要仔细研究getDelta
:
var newTime = self.performance.now();
diff = 0.001 * ( newTime - this.oldTime );
this.oldTime = newTime;
this.elapsedTime += diff;
此函数引用一些未知的隐式全局变量 self
,并调用一些奇数函数 self.performance.now()
。红旗!但是让我们继续挖掘...
事实证明,Three 定义了一个全局变量 self
,其属性performance
与"main"Three.js 文件中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()
的薄包装,这是一种IE9+可用的方法。你最好围绕这个创建你自己的小抽象,以获得一个理智的时钟,并有一个易于实现的reset()
方法。如果我找到具有此功能的npm
包,或者自己制作,我将更新此答案。
解决方法 #3
等待 Three.js Three.Clock
源代码更新,可能是我更新的。由于它有一个开放的票证,因此可能会接受修复它的拉取请求。
在游戏开始时节省时间:var gameStartTime = clock.performance.now()
,并通过从游戏过程中任何其他时间点(包括游戏结束时)从clock.performance.now()
中减去gameStartTime
来计算此后的时间运行。例如:gameStartTime - gameStartTime
等于零,clock.performance.now() - gameStartTime
会给你自游戏开始以来的秒或分钟。
下面是对 JavaScript 中 performance.now()
计时器函数的引用。
这不会重置时钟,但它会生成一个新的时钟对象,并将新值分配给每 5 秒一次的 elapsedTime 变量:
let clock = new THREE.Clock();
const animate = () => {
let elapsedTime = clock.getElapsedTime();
if (elapsedTime > 5) {
clock = new THREE.Clock();
}
window.requestAnimationFrame(animate);
};
这是我用来start
pause
和reset
动画系统运行时的简单解决方法。
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;
- 可以't让我的if语句处理js中的html表单输入
- 使用agility.js进行页面布局和合成
- 使用Clipboard.js复制span文本
- 使用JS如何动态更改显示的html文件中的文本背景颜色
- 强制模板刷新ember.js
- 如何编写HTML输入的JS内联
- Angular JS IE9 Hashbang url rewriting
- 使用JS将数组转换为json对象
- Node.js v6.2.0类扩展不是函数错误
- Meteor.js中的简单时钟或如何重新加载模板
- JS CSS时钟在IE中不工作
- JS时钟在外部JS文件中不起作用
- 在node.js中,有没有办法识别唯一的调用堆栈/时钟周期
- 倒计时时钟 (JS)
- 如何重置三.js时钟
- JS时钟 - 有没有更优雅的方式来编写这段代码
- 在Gulp.js中将时钟改为12小时而不是24小时
- zone.js和Jasmine之间的冲突's的时钟
- 将javascript时钟代码从html文件移动到外部.js文件
- 导线是未定义的和性能滞后THREE.js时钟?虽然它有效