33

I'm using Copperlicht, and I want to create a usable FPS. The demo controls shows why the browser environment makes this a pain.

In order to implement FPS camera control, you need to track the relative mouse position - in other words, its motion, not its absolute screen coordinates. The mouse can leave the browser at any time (rightfully so) and can't be tracked, unless the user initiates a drag event inside the page. Click events change focus and prevent the application from using mouse data as input.

The mouse position can be tracked during drag, but this requires the user to hold down their left mouse button. This isn't good since left clicking is usually used for other things. Holding the button down is also tiring and cumbersome.

The only thing I can think of is automating the middle mouse button. A middle mouse button press keeps focus in the browser, and keeps left/right click events outside the browser window in the browser's focus. Is it possible to cause middle mouse button to stay pressed using JavaScript?

If not, is there a "pure" solution to this ? I'd rather not go to flash or Java or a plugin as an answer.

dtech
  • 13,741
  • 11
  • 48
  • 73
JRowe
  • 363
  • 4
  • 7
  • 1
    I ran into the same problem last week, unfortunately it seems like there is no way to achieve this type of camera using javascript. It would require the mouse pointer to always go back to the center of the canvas after each frame draw, and there is no way to set the mouse position using javascript (which I can understand the reasons). – Delta Apr 25 '11 at 04:10
  • I'd imagine that short of going full screen any "pure" solution would be undesirable in a browser since this would allow webpages (ie, annoying popups) to trap the mouse and prevent you closing the window or leaving the browser. – SpliFF May 08 '11 at 03:27
  • @Trass Vasston: Note that the OP *specifically* addressed this in the question: "The mouse position can be tracked during drag, but this requires the user to hold down their left mouse button. This isn't good since left clicking is usually used for other things. Holding the button down is also tiring and cumbersome." – Piskvor left the building May 13 '11 at 11:43
  • I think this isn't possible in a cross browser way, since it infere with several UI guidelines and thus usually not implemented. For example so-called 'capturing' of the mouse to your own application is usually a bad behaveiour if it is not absolutely clear to the user how to release it. A misbehaveing application could do much pain to the user this way. Event injection like programmatically pressing the mouse button too. The tracking of the mouse outside your page would be a security issue. This is however allowed while dragging as it usually ties the focus to the current UI element. – dronus May 14 '11 at 00:06
  • 4
    I absolutely agree that this is a major issue. Someone should propably take this issue to the browser makers, since it seriously hampers the ability of anyone to build fast paced, action oriented games with mouse interaction. If the browser really wants to compete as a gaming platform, this functionality is required in some way. – Daniel Baulig May 14 '11 at 20:09
  • This is now possible with the Pointer Lock API: https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API – Stefnotch Mar 08 '16 at 18:07
  • I updated my answer see whole code from repo ! – Nikola Lukic Oct 20 '17 at 12:11

8 Answers8

4

This thread is a nice reading on this topic. It seems like prototypes for this functionality are at least suggested for Firefox and Chrome.

Daniel Baulig
  • 10,739
  • 6
  • 44
  • 43
  • Thanks! I'd read through this before, but forgot to bookmark it. I appreciate the link! – JRowe May 18 '11 at 05:21
3

How about making the window fullscreen and then pausing the game if the cursor moves out of the window? I know this doesn't really solve the problem, but it's the best I can think of, without using a plugin of some sort.

Alexander
  • 9,737
  • 4
  • 53
  • 59
  • If the window is fullscreen, the mouse will never move out of the window, as it fill the entire area. – Omiod May 17 '11 at 15:16
  • UVL - When I Alt-Tab and bring up another window, the mouse moves out of the browser window. – Seth May 17 '11 at 17:31
  • While this would be a clever fix, a lot of people have multiple monitors, as I do, myself. Doesn't work. – JRowe May 18 '11 at 05:12
1

It's kind of cheating, but going to about:flags in Chrome and enabling "FPS counter" works for me, :) (but it's not doing it for all browsers nor inside your WebGL app).

Dan Beam
  • 3,632
  • 2
  • 23
  • 27
  • 1
    Oh yeah, also it's only when hardware acceleration is active. – Dan Beam May 20 '11 at 22:19
  • 1
    It doesn't mean what you think it means. This is about FPS camera styles - the First Person Shooter camera style is simply the most iconic, although most modern 3D camera styles require some form of mouse repositioning. – JRowe May 30 '11 at 15:36
0

Right here right now :

I make one with push/pop matrix with glmatrix 0.9 also version 2.0 webgl & glmatrix . Secret - Must translate to zero , rotate and then translate to map position. You have all parameters for first person controler.

See:opengles 1.1. / webgl 1.0 / glmatrix 0.9 or see this example with full colizion.

WebGl 2 / glmatrix 2 Example's (also First Person controller):

Download from bitBucket

Live example

Out of context :

////////////////////////////////////////////////////////
// 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 );

.... End of Draw function

Content of 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;
};

This code allows you to draw 3D objects and folders easily and quickly.Under the principle of one object one line. webgl 3d wourld engine framework zlatnaspirala First person web site look. Used lib : High performance matrix and vector operations for WebGL

Nikola Lukic
  • 4,001
  • 6
  • 44
  • 75
0

I found this example code at 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>
  • It was never a question of tracking mouse position when focus is already in the browser - with FPS and other camera views (top down panning, isometric, rotation bumpers, etc) you have to reposition the pointer or it will move outside the boundaries of the browser window, where it can't be tracked (unless a drag is occuring.) – JRowe May 18 '11 at 05:15
0

We need the window to be able to capture the mouse, as it is seen with some browser plugins, maybe in Java. Flash doesn't have this ability, AFAIK.

As a sidenote, when captured to "get the mouse back" you have to press ESC, and this can be annoying when the app doesn't inform the user properly.

Omiod
  • 11,285
  • 11
  • 53
  • 59
0

(this is the only solution i've seen so far could work for my game project, doing an FPS too)

Implement a Plugin for each browser you intend to support. AFAIK, this is the way they solved the problem with "Quake Live".

Chrome / Chromium -> PPAPI

Firefox & Opera -> NPAPI

IE -> ActiveX

Safari -> Safari plugin development

Btw, the link Daniel Baulig gave you has a nice pointer and solves this problem (on the long run).

Community
  • 1
  • 1
Chiguireitor
  • 3,186
  • 1
  • 20
  • 26
  • 1
    If you are going to implement a plugin, the user will have to download it, and run it. This is a major issue in the web, why would someone download and install something if it's a web-based game? Also, if your users will have to download and run something, why not make that the full game (coded in C++/C#/etc)? – Camilo Martin Jul 01 '12 at 16:44
  • Check my response's date... more than a year ago... back then the "Web" was a lot different and there wasn't so much wide adoption of WebGL based browsers. – Chiguireitor Jul 02 '12 at 13:22
  • I've seen the date, but then or now, the idea seems equally troublesome and silly. Why to have the user play in a browser after he "downloaded your game"? The fun things about browser games is not having to download/install anything. – Camilo Martin Jul 02 '12 at 13:32
  • I'm on the same note there with you, i even helped iron out use cases for an standard that is almost approved right now... But marketing teams sometimes want the thing working on the browser, and you have to comply most of the time. If not, ask the "Quake Live" guys ;) – Chiguireitor Jul 02 '12 at 20:23
  • Ah, I see, in that case it does make sense. Also, there's Unity3D, so it looks like the idea, good or bad, is comercially sound. – Camilo Martin Jul 02 '12 at 21:07
0

At this point in time (Oct 2011) the only way to get real First Person Shooter-style controls is via a browser plugin. Depending on your needs you might also be able to get away with a simple click-and-drag scheme like I'm currently using in my Quake 3 demo, but if you are building an actual game and not a pretty tech demo this is probably not sufficient.

(Note: That's actually what Google did for their GWT port of Quake 2. You have to use the CTRL key to fire, since clicking is used to move your view.)

In the near future, however, we should be receiving a "MouseLock" API that is basically custom-built for this purpose. You can read up on it's progress at Seth Ladd's Blog. Once that comes out we'll have a lot more options for game controls available to us. (Would also help with things like RTS games)

Toji
  • 33,927
  • 22
  • 105
  • 115