鼠标控制第一人称运动JS

时间:2013-08-15 11:14:06

标签: javascript jquery css3

我正在尝试使用鼠标实现第一人称动作。 我确实让它使用键盘但我在使用鼠标实现它时遇到了困难,因为移动到特定的一侧并不是那么清楚(即向左移动可以包括向上或向下移动)。 我想使用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,即使它很棒,因为我希望它支持最大数量的浏览器。

3 个答案:

答案 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)';
};

this is the fiddle

有效!

(我甚至使用Pointer Lock API做了一个例子:fiddle (点击方块开始)


说明:

首先,一个容易设定转速的速度变量 然后,设置了两个旋转变量的mousemove事件 最后一行是根据请求将rotateXrotateY转换转换为matrix3dThis 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

这就是将rotateXrotateY转换为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(",") + ")"
    });
});