FPS controller - move wherever you are facing

Hi,

I have made a custom FPS controller.

When you look up and down (X rotation/Roll), camera.rotation.x adds how much you have moved your mouse up and down.

When you look left and right (Y rotation/Yaw), the player component’s rotation adds the amount you looked left and right.

However, when you move left and right the directions are all messed up and only work relative to the original point.


How do I make it so that you walk left, everywhere you hold down A key?

I heard I should maybe use quaternions or something like that?
Apologies for not providing a playground; I wasn’t sure how to put it there as there are a lot of modules in my project :slight_smile:

You may have a look how it is done here - GitHub - ssatguru/BabylonJS-CharacterController: A CharacterController for BabylonJS

2 Likes

Thank you so much Andrei!!

All fixed :smiley:

For anyone in the future who may have the same issue, i first created a seperate function which listened into keyboard presses and assigned it to some booleans. For example, if A was pressed, moveLeft would be equal to true.
Then in my movement function I applied friction then assigned the movement booleans to directions which I then normalized. I then multiplied forward/right direction, direction, speed and delta and added it to the velocity.
Do note, JS cannot do vector maths, so I used babylon.js’ built-in vector maths functions.

const keyboardMovement = (scene, engine) => {
  scene.registerBeforeRender(() => {
    delta = engine.getDeltaTime();

    direction = new Vector3.Zero();

    forwardDirection = playerCylinder.getDirection(new Vector3(0, 0, 1));
    forwardDirection.normalize();
    rightDirection = playerCylinder.getDirection(new Vector3(1, 0, 0));
    rightDirection.normalize();

    //Slows down the current movement like a friction force
    velocity.x *= friction * delta;
    velocity.z *= friction * delta;

    //Gravity is applied
    velocity.y += 9.8 * 100.0 * delta; //100.0 = mass

    direction.z = Number(moveBackward) - Number(moveForward);
    direction.x = Number(moveLeft) - Number(moveRight);
    direction.normalize(); // gives direction a length of 1 so diagonal movement isn't faster

    if (moveForward || moveBackward || moveLeft || moveRight) {
      //JS can't do maths with built in operators like * or + for vectors, so we have to use their custom vector maths functions

      //velocity += rightDirection * direction.x * speed * delta;
      // left & right
      velocity = velocity.add(
        rightDirection.scale(direction.x * speed * delta)
      );

      //velocity += forwardDirection * direction.z * speed * delta;
      // forward & back
      velocity = velocity.add(
        forwardDirection.scale(direction.z * speed * delta)
      );
    }

    //Apply velocities to position
    playerCylinder.position.x += -velocity.x * delta; //Left/Right

    playerCylinder.position.z += -velocity.z * delta; //Forwards/Backwards
  });
};
2 Likes