因此,大约一个小时前,我经历了一段令人愉快而尴尬的时刻,即经过很长一段时间之后,有些声音突然响起。推到30,我终于有了窦和余弦。只能描述为基本上重新实现了转盘之后的情节。
为了使WASD控件在两个轴上移动,并考虑玩家的观看方向,我决定使用一个简单的开关:
switch (key) {
case 'up':
movement.z -= 1 * modulation.z;
movement.x += 1 * modulation.x;
break;
case 'down':
movement.z += 1 * modulation.z;
movement.x -= 1 * modulation.x;
break;
case 'left':
movement.x -= 1 * modulation.z;
movement.z -= 1 * modulation.x;
break;
case 'right':
movement.x += 1 * modulation.z;
movement.z += 1 * modulation.x;
break;
...
}
...,其中modulation.z和.x将基于玩家所面对的方向。调制值需要在-1至+1的范围内。 (这应该是我的第一个线索,是的!)因此,我帮助自己学会了一些可信赖的笔和纸,并且由于对我的9年级教育非常不了解,我想到了:
function setModulation(rotation) {
var rotationTemp = 0;
var modulation = {};
rotationTemp = rotation;
if (rotationTemp > 180) {
rotationTemp = 360 - rotationTemp;
}
rotationTemp /= 180;
modulation.z = 1 - rotationTemp * 2;
rotationTemp = rotation + 90;
if (rotationTemp > 180) {
rotationTemp = 360 - rotationTemp;
}
rotationTemp /= 180;
modulation.x = 1 - rotationTemp * 2;
modulation.x *= -1;
return modulation;
};
同时学习和/或记住了一点,在重新阅读此代码后,它突然出现在我身上:这是因果关系和罪过的工作。不好意思
function setModulationMath(rotation) {
var modulation = {};
modulation.z = Math.cos(rotation * Math.PI / 180);
modulation.x = Math.sin(rotation * Math.PI / 180);
return modulation;
};
到目前为止,一切顺利!使用数学是为了数学!但是后来我检查了性能。在FF,Chrome和IE中,我自己的“实现”要快得多。使用1.000.000次迭代,我的本地设置获得了35%至45%的增益。
任何人都知道为什么?仅仅是Math.cos()/ .sin()吗?可衡量的增长远远超出了人们的预期,不是吗?有人愿意分享她的见解吗?
function setModulationMath(rotation) {
var modulation = {};
modulation.z = Math.cos(rotation * Math.PI / 180);
modulation.x = Math.sin(rotation * Math.PI / 180);
return modulation;
};
function setModulation(rotation) {
var rotationTemp = 0;
var modulation = {};
rotationTemp = rotation;
if (rotationTemp > 180) {
rotationTemp = 360 - rotationTemp;
}
rotationTemp /= 180;
modulation.z = 1 - rotationTemp * 2;
rotationTemp = rotation + 90;
if (rotationTemp > 180) {
rotationTemp = 360 - rotationTemp;
}
rotationTemp /= 180;
modulation.x = 1 - rotationTemp * 2;
modulation.x *= -1;
return modulation;
};
var iterations = 1000000;
console.time('setModulation');
for(var i = 0; i < iterations; i++ ){
setModulation(i, i / 2);
};
console.timeEnd('setModulation')
console.time('setModulationMath');
for(var i = 0; i < iterations; i++ ){
setModulationMath(i, i / 2);
};
console.timeEnd('setModulationMath')
最佳答案
您的功能可能会更快。但是,比较没有任何意义,因为函数产生的结果完全不同。让我们以错误为基准:
var err_z = 0;
var err_x = 0;
for (var i = 0; i < 360; ++i){
var mm = setModulationMath(i);
var m = setModulation(i);
err_z += Math.abs(mm.z - m.z);
err_x += Math.abs(mm.x - m.x);
}
还有...
err_z == 49.17730025861921
err_x == 113.58865012930961
真不好如果两者完全相似,则期望值接近0。
虽然我的第一个假设是我必须以某种方式伪造它:它完美地起作用了。两种功能均提供相同的调制值。话虽这么说:我很高兴得知这是一种仅适用于[x] ...::)的hack。
在z轴上的平均误差可证明是0.137,在x轴上的平均误差是0.316。这对您可能已经足够好了,但是肯定会有一些差异较大的值。您是否仅检查正交方向?在这种情况下,您需要的是
switch
,而不是三角函数。编辑:哦,这是z部分的图形。波浪线是余弦,直线是您的近似值。
但是我离题了。
(尝试)推出自己的触发函数,数学函数等的实现并不一定很糟糕。它确实取决于应用程序的具体情况,有时您会发现不需要这种精度或角度只能表示为整数度数。在这种情况下,使用更简单的近似表或查找表可能会有所帮助。
实际上,JavaScript(以及许多其他标准库)中的正弦和余弦都经过了很好的优化和非常精确的设计。