【问题标题】:How can I implement a FPS view with WebGL inside a browser?如何在浏览器中使用 WebGL 实现 FPS 视图?
【发布时间】:2011-04-24 05:17:37
【问题描述】:

我正在使用Copperlicht,我想创建一个可用的 FPS。 The demo 控件说明了为什么浏览器环境让这很痛苦。

为了实现 FPS 相机控制,您需要跟踪鼠标的相对位置 - 换句话说,它的运动,而不是它的绝对屏幕坐标。鼠标可以随时离开浏览器(这是理所当然的)并且无法被跟踪,除非用户在页面内发起拖动事件。点击事件改变焦点并阻止应用程序使用鼠标数据作为输入。

可以在拖动过程中跟踪鼠标位置,但这需要用户按住鼠标左键。这不好,因为左键单击通常用于其他事情。按住按钮也很累很麻烦。

我唯一能想到的就是自动化鼠标中键。按下鼠标中键将焦点保持在浏览器中,并将浏览器窗口外的左/右键单击事件保持在浏览器的焦点中。是否可以使用 JavaScript 使鼠标中键保持按下状态?

如果没有,是否有“纯”解决方案?我宁愿不使用 Flash、Java 或插件作为答案。

【问题讨论】:

  • 上周我遇到了同样的问题,不幸的是似乎没有办法使用javascript来实现这种类型的相机。它会要求鼠标指针在每帧绘制后总是回到画布的中心,并且没有办法使用javascript设置鼠标位置(我可以理解原因)。
  • 我想如果没有全屏显示,任何“纯”解决方案在浏览器中都是不可取的,因为这将允许网页(即烦人的弹出窗口)捕获鼠标并阻止您关闭窗口或离开浏览器。
  • @Trass Vasston:请注意,OP 专门在问题中解决了这个问题:“鼠标位置可以在拖动过程中被跟踪,但这需要用户按住左鼠标按钮。这不好,因为左键单击通常用于其他操作。按住按钮也很累而且很麻烦。"
  • 我认为这在跨浏览器的方式中是不可能的,因为它会根据几个 UI 指南进行推断,因此通常不会实现。例如,如果用户不完全清楚如何释放鼠标,那么所谓的“捕获”鼠标到您自己的应用程序通常是一种不良行为。行为不端的应用程序可能会给用户带来很多痛苦。事件注入也像以编程方式按下鼠标按钮。在您的页面外跟踪鼠标将是一个安全问题。但是,在拖动时允许这样做,因为它通常会将焦点与当前 UI 元素联系起来。
  • 我绝对同意这是一个重大问题。有人应该将这个问题提交给浏览器制造商,因为它严重阻碍了任何人通过鼠标交互构建快节奏、面向动作的游戏的能力。如果浏览器真的想作为一个游戏平台竞争,这个功能在某种程度上是必需的。

标签: javascript html 3d webgl copperlicht


【解决方案1】:

这个thread 是关于这个主题的好读物。似乎至少为FirefoxChrome 建议了此功能的原型。

【讨论】:

  • 谢谢!我以前读过这个,但忘了给它加书签。我感谢这个链接!
【解决方案2】:

如果光标移出窗口,让窗口全屏然后暂停游戏怎么样?我知道这并不能真正解决问题,但这是我能想到的最好的方法,无需使用某种插件。

【讨论】:

  • 如果窗口是全屏的,鼠标永远不会移出窗口,因为它会填满整个区域。
  • UVL - 当我 Alt-Tab 并打开另一个窗口时,鼠标移出浏览器窗口。
  • 虽然这将是一个聪明的解决方案,但很多人都有多个显示器,就像我自己一样。没用。
【解决方案3】:

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

【讨论】:

  • 哦,是的,也只有在硬件加速处于活动状态时。
  • 这并不意味着你认为它意味着什么。这是关于 FPS 相机风格 - 第一人称射击相机风格只是最具标志性的,尽管大多数现代 3D 相机风格需要某种形式的鼠标重新定位。
【解决方案4】:

我在以下位置找到了此示例代码 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 和其他相机视图(自上而下平移、等距、旋转保险杠等),您必须重新定位指针或它将移动到浏览器窗口的边界之外,无法对其进行跟踪(除非发生拖动。)
【解决方案5】:

我们需要窗口能够捕获鼠标,就像在一些浏览器插件中看到的那样,可能在 Java 中。 Flash 没有这种能力,AFAIK。

作为旁注,当捕获到“让鼠标返回”时,您必须按 ESC,如果应用程序没有正确通知用户,这可能会很烦人。

【讨论】:

    【解决方案6】:

    (这是迄今为止我看到的唯一一个适用于我的游戏项目的解决方案,也适用于 FPS)

    为您打算支持的每个浏览器实施一个插件。 AFAIK,这就是他们解决“Quake Live”问题的方法。

    Chrome / Chromium -> PPAPI

    Firefox 和 Opera -> NPAPI

    IE -> ActiveX

    Safari -> Safari plugin development

    顺便说一句,Daniel Baulig 给你的链接有一个很好的指针并解决了这个问题(从长远来看)。

    【讨论】:

    • 如果你要实现一个插件,用户必须下载并运行它。这是网络中的一个主要问题,如果它是基于网络的游戏,为什么有人会下载并安装一些东西?此外,如果您的用户必须下载并运行某些内容,为什么不将其制作成完整的游戏(使用 C++/C#/etc 编码)?
    • 查看我的回复日期...一年多以前...当时“Web”有很大不同,基于 WebGL 的浏览器并没有被广泛采用。
    • 我已经看到了日期,但无论从那时还是现在,这个想法似乎都同样麻烦和愚蠢。为什么要让用户“下载了你的游戏”后在浏览器中玩?浏览器游戏的有趣之处在于无需下载/安装任何东西。
    • 我和你有同样的看法,我什至帮助解决了一个现在几乎被批准的标准的用例......但营销团队有时希望这个东西在浏览器上工作,你必须在大部分时间里遵守。如果没有,请询​​问“Quake Live”人员;)
    • 啊,我明白了,在这种情况下确实有意义。此外,还有 Unity3D,所以无论好坏,看起来这个想法在商业上都是合理的。
    【解决方案7】:

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

    (注意:这实际上是 Google 为 Quake 2 的 GWT 端口所做的。你必须使用 CTRL 键来触发,因为点击是用来移动你的视图。)

    不过,在不久的将来,我们应该会收到一个基本上为此目的定制的“MouseLock”API。你可以在Seth Ladd's Blog 阅读它的进展。一旦出现,我们将有更多可供我们使用的游戏控制选项。 (也有助于 RTS 游戏之类的事情)

    【讨论】:

      【解决方案8】:

      现在就在这里:

      我用 glmatrix 0.9 和版本 2.0 webgl & glmatrix 制作了一个推/弹出矩阵。 秘密 - 必须平移到零,旋转然后平移到地图位置。您拥有第一人称控制器的所有参数。

      见:opengles 1.1. / webgl 1.0 / glmatrix 0.9 或者查看这个完整的例子。

      WebGl 2 / glmatrix 2 示例(也是第一人称控制器):

      Download from bitBucket

      Live example

      断章取义:

      ////////////////////////////////////////////////////////
      // 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 的高性能矩阵和向量运算

      【讨论】:

        猜你喜欢
        • 2017-01-27
        • 2017-11-21
        • 1970-01-01
        • 2022-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-20
        • 1970-01-01
        相关资源
        最近更新 更多