我正在尝试使用鼠标实现第一人称动作。
我确实让它使用键盘但我在使用鼠标实现它时遇到了困难,因为移动到特定的一侧并不是那么清楚(即向左移动可以包括向上或向下移动)。
我想使用matrix3d
来接收更改的职位值。
编辑#2 这是jsfiddle。
编辑我已经粘贴了我设法解决的新代码:
$(document).on('mousemove', function (e) {
var MOVE = 10; // how much to move
var XTURN = 1; // how much to rotate
var YTURN = 1; // how much to rotate
var transformer, origMat, translationMatrix, result;
transformer = document.getElementById("transformer");
if ($.browser.webkit)
origMat = new WebKitCSSMatrix(window.getComputedStyle(transformer).webkitTransform);
//turn left
if (e.pageX < xPrev) {
if (XTURN < 0) {
XTURN *= -1;
}
xPrev = e.pageX;
//turn right
} else {
if (XTURN > 0) {
XTURN *= -1;
}
xPrev = e.pageX;
}
//look up
if (e.pageY < yPrev) {
if (YTURN < 0) {
YTURN *= -1;
}
yPrev = e.pageY;
//look down
} else {
if (YTURN > 0) {
YTURN *= -1;
}
yPrev = e.pageY;
}
translationMatrix = new WebKitCSSMatrix("matrix3d(" + cos(XTURN).toFixed(10) + ",0," + sin(XTURN).toFixed(10) + ",0,0,"+ cos(-YTURN).toFixed(10) +","+ sin(YTURN).toFixed(10) +",0, " + sin(-XTURN).toFixed(10) + ","+ sin(-YTURN).toFixed(10) +"," + cos(XTURN).toFixed(10) + ",0,0,0,0,1)");
transformer.style.webkitTransform = translationMatrix.multiply(origMat).toString();
});
正如你所看到的(对于一个行矩阵,我很抱歉)我在相同的矩阵变化上说明X和Y旋转的变化,然后提交它,现在的问题是cos(XTURN).toFixed(10)
,它可以与X和Y旋转有关,所以你可以看到它有效但不完美。
非常感谢任何提示/想法。
P.S我不想使用Pointer Lock API,即使它很棒,因为我希望它支持最大数量的浏览器。
答案 0 :(得分:3)
我不太清楚你的高级目标是什么。听起来你正试图在JS和CSS中实现类似反恐精英的游戏。哪个太棒了!对于这个答案的其余部分,我将假设您正在尝试做类似的事情。
实际上,您必须使用Pointer Lock API。否则,只能向左移动鼠标就无法转身。您将点击浏览器窗口的边缘并停止转动。浏览器支持不是很好,但它对游戏玩家来说是一个更好的体验!
为了使用CSS变换渲染您的世界,您需要进行一系列复杂的变换,以便为游戏世界中可见的每个对象的每一侧生成矩阵。这是因为浏览器的透视图始终沿Z轴直接观察。因此,为了在观察者的眼睛周围“动画”动画,你必须翻译并旋转它们。经过一番探讨之后,我得出的结论是,在CSS中进行所有变换都非常慢(而且很复杂!)。但从不担心,还有另一种方式! WebGL或Canvas救援!
看看Isaac Sukin的游戏Nemesis。这是一个很好的例子,他写了tutorial来提出类似的东西!它基于Three.js的库被广泛使用,并且具有非常易理解的API。它几乎完成了所有困难的部分,让你只创造一个3D世界!
祝你好运!
答案 1 :(得分:3)
Pure JavaScript大多比库更好(除非它是“ Code less do more ”的东西),
因为你可以理解你的代码真正做了什么。
这是我的整个JavaScript代码:
var velocity = 0.5;
document.onmousemove = function(e) {
var angleX = e.pageY * velocity * Math.PI / 180;
var angleY = e.pageX * velocity * Math.PI / 180;
document.getElementById('transformer').style.webkitTransform = 'matrix3d(' + Math.cos(-angleY) + ',0,' + Math.sin(-angleY) + ',0,' + (Math.sin(angleX)*Math.sin(-angleY)) + ',' + Math.cos(angleX) + ',' + (-Math.sin(angleX)*Math.cos(-angleY)) + ',0,' + (-Math.cos(angleX)*Math.sin(-angleY)) + ',' + Math.sin(angleX) + ',' + (Math.cos(angleX)*Math.cos(-angleY)) + ',0,0,0,0,1)';
};
有效!
(我甚至使用Pointer Lock API做了一个例子:fiddle (点击方块开始)
说明:
首先,一个容易设定转速的速度变量
然后,设置了两个旋转变量的mousemove
事件
最后一行是根据请求将rotateX
和rotateY
转换转换为matrix3d
。
This Stackoverflow question帮助我找到了以下解决方案。
rotateX(angleX)
等于以下矩阵:
1 0 0 0
0 cos(angleX) -sin(angleX) 0
0 sin(angleX) cos(angleX) 0
0 0 0 1
rotateY(angleY)
等于以下矩阵:
cos(angleY) 0 sin(angleY) 0
0 1 0 0
-sin(angleY) 0 cos(angleY) 0
0 0 0 1
要将它们一起使用,您需要将两个矩阵相乘。 所以我写了一个小的JavaScript工具给我计算我需要做的计算来得到这个乘法的结果。
结果:
cos(angleY) sin(angleX)*sin(angleY) cos(angleX)*sin(angleY) 0
0 cos(angleX) -sin(angleX) 0
-sin(angleY) sin(angleX)*cos(angleY) cos(angleX)*cos(angleY) 0
0 0 0 1
这就是将rotateX
和rotateY
转换为matrix3d
的方式。
希望有所帮助:)
答案 2 :(得分:2)
使用四元数非常简单。我在Google closure library找到了一个实现,所以我做了一个例子(同样,检查the jsFiddle):
goog.require('goog.vec.Quaternion');
var velocity = 0.5;
var lastX = null;
var lastY = null;
var angleX = 0;
var angleY = 0;
$(document).on('mousemove', function (e) {
if (lastX == null) lastX = e.pageX;
if (lastY == null) lastY = e.pageY;
angleX += (e.pageX - lastX) * velocity * Math.PI / 180;
angleY += (e.pageY - lastY) * velocity * Math.PI / 180;
lastX = e.pageX;
lastY = e.pageY;
var quat = goog.vec.Quaternion.concat(
goog.vec.Quaternion.fromAngleAxis(angleX, [0, 1, 0], []),
goog.vec.Quaternion.fromAngleAxis(-angleY, [1, 0, 0], []), []);
var matrix = goog.vec.Quaternion.toRotationMatrix4(quat, []);
$("#transformer").css({
webkitTransform: "matrix3d(" + matrix.join(",") + ")"
});
});