javascriptthree.jsgame-physicsphysijs

Three.JS FPS Controls Strafing Left and Right


I am setting up a simple demo to test player controls for a FPS. I have the mouse rotating the camera and the player can move with W-A-S-D. My question is what is the algorithm I need for the player to be able to move left and right relative to the direction the camera is facing? The controls to move forward and backward work great, but I ran into trouble trying to get the left and right movements working.

I'm using THREE.JS and PhysiJS (Physics engine).

Here is a segment of my code below...

    // the direction the camera is pointing in
    var cameraLookVector = this.controls.getDirection(this.vDirection);         
                
    // Player Movement
    this.v = new THREE.Vector3(0,0,0);
    if(keyboard.pressed("W")) { // Move forward
        this.v.x -= cameraLookVector.x * (Player.SPEED * delta * this.q); // works great
        this.v.z -= cameraLookVector.z * (Player.SPEED * delta * this.q);
    }
    if(keyboard.pressed("A")) { // Move left
        // Sets position relative to the world and not the direction the camera is facing
        this.v.x -= Player.SPEED * delta * this.q;
        /* Tried this but it didn't work
        this.v.x -= Math.cos(cameraLookVector * (Math.PI/180)) * (Player * delta * this.q);
        this.v.z -= Math.sin(cameraLookVector * (Math.PI/180)) * (Player * delta * this.q);
        */
    }
    if(keyboard.pressed("S")) { // Move backward
        this.v.x -= cameraLookVector.x * (Player.SPEED * delta * this.q); // works great
        this.v.z -= cameraLookVector.z * (Player.SPEED * delta * this.q);
    }
    if(keyboard.pressed("D")) { // Move right
        // Sets position relative to the world and not the direction the camera is facing
        this.v.x += Player.SPEED * delta * this.q;
    }
    
    this.bodyMesh.setLinearVelocity(this.v);

The left and right controls set the player's position relative to the world. For example the player will start out moving to the left of the screen if I hold down 'A', but if I rotate the camera with my mouse, the player will be moving into the screen. I want the player's left and right position updated relative to the direction of the camera so from the player's perspective they're always strafing left or right.

Thank you for any help!


Solution

  • A less computationally intensive way to calculate a vector in the left or right direction is by using the cross-product of of the cameraLookVector and a constant "up" direction. This assumes that the cameraLookVector is never parallel with this "up".

    Cross-product diagram

    In this image, we can choose the b vector as the direction the camera is looking, a as a constant up, and a x b as a non-unit vector in the direction you want for a left strafe.

    var vectorUp = new THREE.Vector3(0, 1, 0);
    
    
    // Left vector
    var coefficient = Player.SPEED * delta * this.q;
    
    this.v.copy(new THREE.Vector3().crossVectors(vectorUp, cameraLookVector).normalize().multiplyScalar(coefficient));