10

我正在尝试使用鼠标实现第一人称动作。我确实让它与键盘一起使用,但我在使用鼠标实现它时遇到了困难,因为向特定一侧的移动不是那么清楚(即向左移动可以包括向上或向下移动)。我想使用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 旋转有关的问题,所以你可以看到它有效但并不完美。将不胜感激任何提示/想法。

PS 我不想使用Pointer Lock API,即使它很棒,因为我希望它支持最大数量的浏览器。

4

3 回答 3

3

我不太清楚你的高级目标是什么。听起来您正在尝试在 JS 和 CSS 中实现类似 Counterstrike 的游戏。太棒了!对于这个答案的其余部分,我将假设您正在尝试做类似的事情。

实际上,您必须使用 Pointer Lock API。否则,您将无法仅通过向左移动鼠标来转身。你会碰到浏览器窗口的边缘并停止转动。浏览器支持不是很好,但它对游戏玩家来说是更好的体验!

为了使用 CSS 变换来渲染您的世界,您需要执行一系列复杂的变换来为游戏世界中每个可见对象的每一面生成矩阵。这是因为浏览器的视角总是直接沿着 Z 轴看。因此,为了“围绕”观看者的眼睛制作动画,您必须平移和旋转它们。经过一番摸索,我得出结论,在 CSS 中进行所有转换都非常缓慢(而且复杂!)。但不要害怕,还有另一种方法!WebGL 或 Canvas 来救援!

看看 Isaac Sukin 的游戏Nemesis。这是一个很好的例子,他写了一个教程来提出类似的东西!它所基于的库 Three.js 使用非常广泛,并且具有非常易于理解的 API。它几乎消除了所有困难的部分,让您只需制作一个 3D 世界!

祝你游戏好运!

于 2013-08-19T01:35:32.533 回答
3

纯 JavaScript 大多比库好(除非它是“代码少做多”的事情),
因为您可以理解您的代码的真正作用。

这是我的整个 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设置了两个旋转变量的事件。
最后一行是根据要求进行转换rotateXrotateY转换matrix3d这个 Stackoverflow 问题帮助我找到了以下解决方案。


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和转换rotateYmatrix3d.

希望能帮助到你 :)

于 2013-08-23T20:09:46.073 回答
2

使用四元数确实更容易。我在Google 闭包库中找到了一个实现,所以我做了一个例子(另外,检查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(",") + ")"
    });
});
于 2013-08-23T14:02:13.103 回答