如何在浏览器中使用WebGL实现FPS视角?

33
我正在使用Copperlicht,希望创建可用的FPS。 演示控件显示了为什么浏览器环境会让这很麻烦。
为了实现FPS相机控制,需要跟踪相对鼠标位置 - 换句话说,它的运动,而不是其绝对屏幕坐标。鼠标随时可以离开浏览器(理所当然),除非用户在页面内启动拖动事件,否则无法跟踪鼠标。单击事件会更改焦点并防止应用程序将鼠标数据用作输入。
鼠标位置可以在拖动期间跟踪,但这需要用户按住左键。这不好,因为左键通常用于其他事情。按住按钮也很累人和繁琐。
我唯一能想到的就是自动化中间鼠标按钮。中间鼠标按钮按下后,保持浏览器的焦点,并使左/右单击事件保持在浏览器窗口外的浏览器焦点中。是否可能使用JavaScript使中间鼠标按钮保持按下状态?
如果不行,是否有“纯”解决方案?我不想用Flash或Java或插件作为答案。

1
上周我遇到了同样的问题,不幸的是似乎没有办法使用JavaScript实现这种类型的相机。每次绘制帧后,它需要将鼠标指针始终返回到画布的中心,并且无法使用JavaScript设置鼠标位置(我可以理解原因)。 - Delta
我想,在浏览器中,除了全屏之外的任何“纯粹”解决方案都不可取,因为这会允许网页(即烦人的弹窗)捕获鼠标并防止您关闭窗口或离开浏览器。 - SpliFF
4
我完全同意这是一个重大问题。可能应该有人将此问题提交给浏览器制造商,因为这严重影响了任何人使用鼠标交互构建快节奏、动作导向游戏的能力。如果浏览器真的想要成为游戏平台竞争者,就必须以某种方式提供此功能。 - Daniel Baulig
现在使用指针锁定API已经成为可能:https://developer.mozilla.org/zh-CN/docs/Web/API/Pointer_Lock_API - Stefnotch
我更新了我的回答,请从代码库中查看完整代码! - Nikola Lukic
显示剩余2条评论
8个回答

4

这个帖子讨论了一个有关IT技术的话题。看起来,针对这一功能的原型至少已经在FirefoxChrome中被建议。


谢谢!我之前已经阅读过这篇文章,但是忘记收藏了。感谢提供链接! - JRowe

3

如果将窗口设置为全屏,然后当光标移出窗口时暂停游戏,这样怎么样?我知道这并不能真正解决问题,但这是我能想到的最好的方法,而不使用任何插件。


如果窗口是全屏的,鼠标将永远不会移出窗口,因为它填满了整个区域。 - Omiod
UVL - 当我使用Alt-Tab切换到另一个窗口时,鼠标会移出浏览器窗口。 - Seth
虽然这可能是一个聪明的解决办法,但很多人都有多个显示器,就像我自己一样。它行不通。 - JRowe

1

这有点作弊,但在Chrome中转到about:flags并启用“FPS计数器”对我有效,:)(但它并不适用于所有浏览器或您的WebGL应用程序内部)。


1
哦,是的,只有在硬件加速处于活动状态时才会出现。 - Dan Beam
1
它的意思并不是你想象中的那样。这是关于FPS相机风格的 - 第一人称射击游戏相机风格只是最具标志性的,尽管大多数现代3D相机风格需要某种形式的鼠标重新定位。 - JRowe

0
我在这里找到了一个示例代码: http://bitdaddys.com/javascript/example3run.html
 <html>
<head>
<title>JavaScript Example of Mouse Position Tracking</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<body>
<form name=thisform>
<table border=0>
<tr><td colspan=2>Position Of Cursor</td></tr>
<tr><td>X <input type=text name=x value=""></td>
    <td>Y <input type=text name=y value=""></td>

</tr>
</table>
</form>

<script type=text/javascript>
    var isIE = document.all?true:false;
    if (!isIE) document.captureEvents(Event.MOUSEMOVE);
    document.onmousemove = getMousePosition;
    function getMousePosition(mp) {
      var _x;
      var _y;
      if (!isIE) {
        _x = mp.pageX;
        _y = mp.pageY;
      }
      if (isIE) {
        _x = event.clientX + document.body.scrollLeft;
        _y = event.clientY + document.body.scrollTop;
      }
      document.thisform.x.value=_x;
      document.thisform.y.value=_y;
      return true;
    }
</script>


</body>
</html>

当焦点已经在浏览器中时跟踪鼠标位置从来不是问题——随着FPS和其他摄像机视图(自上而下的平移、等角线、旋转凸轮等),您必须重新定位指针,否则它会移动到浏览器窗口的边界之外,无法被跟踪(除非拖动正在发生)。 - JRowe

0

就在此时此刻:

我使用 glmatrix 0.9 和版本 2.0 的 webgl & glmatrix 创建了一个带有推/弹出矩阵的程序。 秘诀-必须将其转换为零,旋转并将其转换为地图位置。您拥有第一人称控制器的所有参数。

请参见:opengles 1.1. / webgl 1.0 / glmatrix 0.9 或查看此示例以获取完整的碰撞检测。

WebGl 2 / glmatrix 2 示例(还包括第一人称控制器):

从 bitBucket 下载

实时示例

超出上下文:

////////////////////////////////////////////////////////
// Somewhere in draw function  ....
////////////////////////////////////////////////////////

mat4.identity(object.mvMatrix);
this.mvPushMatrix(object.mvMatrix,this.mvMatrixStack);

    ////////////////////////////////////////////////////////
    if (App.camera.FirstPersonController==true){camera.setCamera(object)}

    ////////////////////////////////////////////////////////
    mat4.translate(object.mvMatrix, object.mvMatrix, object.position.worldLocation );
    mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotValue), object.rotDirection.RotationVector );

...绘制函数结束

SetCamera 的内容:

var camera = new Object();

/* Set defaults                                  */
camera.pitch     = 0;
camera.pitchRate = 0;
camera.yaw       = 0;
camera.yawRate   = 0;
camera.xPos      = 0;
camera.yPos      = 0;
camera.zPos      = 0;
camera.speed     = 0;
camera.yawAmp    = 0.05;
camera.pitchAmp    = 0.007;

keyboardPress = defineKeyBoardObject();

camera.setCamera = function(object) {
    /* Left Key  or A                            */
    if (keyboardPress.getKeyStatus(37) || keyboardPress.getKeyStatus(65) ||  App.camera.leftEdge == true) {

        camera.yawRate = 20;
        if (App.camera.leftEdge == true) camera.yawRate = 10;
    }
    /* Right Key or D                            */
    else if (keyboardPress.getKeyStatus(39) || keyboardPress.getKeyStatus(68) ||  App.camera.rightEdge == true) {

        camera.yawRate = -20;
        if (App.camera.rightEdge == true) camera.yawRate = -10;
    }
    else {
       // camera.yawRate = 0;
    }



    /* Up Key    or W                            */
    if (keyboardPress.getKeyStatus(38) || keyboardPress.getKeyStatus(87)) {
        camera.speed = 0.03;
    }
    /* Down Key  or S                            */
    else if (keyboardPress.getKeyStatus(40) || keyboardPress.getKeyStatus(83)) {
        camera.speed = -0.03;
    }
    else {
        camera.speed = 0;
    }
    /* Page Up
    if (keyboardPress.getKeyStatus(33)) {
        camera.pitchRate = 100;
    }
    /* Page Down
    else if (keyboardPress.getKeyStatus(34)) {
        camera.pitchRate = -100;
    }
    else {
        camera.pitchRate = 0;
    }
    */
    /* Calculate yaw, pitch and roll(x,y,z) */
    if (camera.speed != 0) {

        camera.xPos -= Math.sin(degToRad(camera.yaw)) * camera.speed;
        camera.yPos = 0;
        camera.zPos -= Math.cos(degToRad(camera.yaw)) * camera.speed;

    }
    camera.yaw   += camera.yawRate   * camera.yawAmp   ;
    camera.pitch += camera.pitchRate * camera.pitchAmp ;

    mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(-camera.pitch), [1, 0, 0]);
    mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(-camera.yaw), [0, 1, 0]);

   // mat4.translate(object.mvMatrix, object.mvMatrix, [camera.yaw, -camera.pitch, 0]);
     mat4.translate(object.mvMatrix, object.mvMatrix, [-camera.xPos , -camera.yPos  , -camera.zPos ]);

    camera.yawRate   = 0;
    camera.pitchRate = 0;
};

这段代码可以让你轻松快速地绘制3D对象和文件夹,遵循一个对象一行的原则。使用webgl 3d世界引擎框架zlatnaspirala,实现第一人称网站视角。所用库包括:为WebGL提供高性能矩阵和向量操作。


0

我们需要窗口能够捕获鼠标,就像一些浏览器插件中看到的那样,也许可以使用Java实现。据我所知,Flash没有这个功能。

顺便提一下,当捕获鼠标后,要“还原”鼠标,必须按ESC键,如果应用程序没有正确地通知用户,这可能会很烦人。


0

(这是目前我看过唯一可能适用于我的游戏项目的解决方案,因为我也在做第一人称射击游戏)

为每个你打算支持的浏览器实现一个插件。据我所知,“Quake Live”就是通过这种方式解决了此问题。

Chrome / Chromium -> PPAPI

Firefox & Opera -> NPAPI

IE -> ActiveX

Safari -> Safari 插件开发

顺便说一下,Daniel Baulig 给你提供的链接有一个很好的指针,并能从长远角度解决这个问题。


1
如果你打算实现一个插件,用户就必须下载并运行它。这是Web上的一个主要问题,为什么有人会下载和安装某些东西,如果游戏已经基于Web了呢?另外,如果你的用户需要下载和运行某些东西,为什么不把整个游戏(用C++/C#等编写)作为下载选项呢? - Camilo Martin
请检查我的回复日期...已经超过一年了...那时候的"Web"有很大的不同,基于WebGL的浏览器也没有得到广泛的采用。 - Chiguireitor
我看过日期,但无论是过去还是现在,这个想法似乎同样令人烦恼和愚蠢。为什么要让用户在下载了游戏之后在浏览器中玩呢?浏览器游戏的有趣之处在于不需要下载/安装任何东西。 - Camilo Martin
我和你的想法一致,我甚至帮助梳理了一个几乎已经获得批准的标准的用例...但是营销团队有时候想要在浏览器上运行,而且大多数情况下你必须遵守。如果不这样做,就问问“Quake Live”的人吧 ;) - Chiguireitor
啊,我明白了,那样的话确实有道理。此外,还有Unity3D,所以这个想法,不管好坏,商业上看起来是可行的。 - Camilo Martin

0

截至2011年10月,获得真正的第一人称射击游戏样式控制的唯一方法是通过浏览器插件。根据您的需求,您可能还可以使用简单的点击和拖动方案,就像我目前在Quake 3演示中使用的那样,但是如果您正在构建一个实际的游戏而不是漂亮的技术演示,则可能不足够。

(注意:这实际上是Google为其Quake 2的GWT端口所做的。您必须使用CTRL键来开火,因为单击用于移动视图。)

然而,在不久的将来,我们应该会收到一个“MouseLock”API,该API基本上是为此目的量身定制的。您可以在Seth Ladd的博客中了解其进展情况。一旦发布,我们将有更多的游戏控制选项可供选择。(也有助于像RTS游戏这样的问题)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接