Skip to content
This repository has been archived by the owner on Feb 10, 2023. It is now read-only.

[Feature] First Person movement code #69

Closed
IRobot1 opened this issue Mar 11, 2022 · 2 comments
Closed

[Feature] First Person movement code #69

IRobot1 opened this issue Mar 11, 2022 · 2 comments

Comments

@IRobot1
Copy link
Contributor

IRobot1 commented Mar 11, 2022

I noticed where wasn't an easy way to move and look around a scene using mouse and keyboard. Code below might be a good candidate for an easy drop-in SOBA component.

import { Component, Input } from '@angular/core';
import { Camera, Vector3 } from 'three';
import { NgtCanvasStore, NgtRender } from '@angular-three/core';

//
// adapted from three.js games fps example https://github.com/mrdoob/three.js/blob/master/examples/games_fps.html
//
@Component({
  selector: 'pointer-lock-controls',
  template: '<ngt-group (ready)="ready()" (animateReady)="animate($event.state)"></ngt-group>'
})
export class PointerLockControlsComponent {
  @Input() container?: HTMLElement;
  @Input() viewerheight = 1.5;
  @Input() movespeed = 1;
  @Input() rotatefactor = 2000;

  private keyStates = new Map<string, boolean>([]);
  private camera!: Camera;

  constructor(private canvasStore: NgtCanvasStore) { }

  ready() {
    const camera = this.canvasStore.get((s) => s.camera);
    camera.rotation.order = 'YXZ';
    this.camera = camera;

    // movement
    document.addEventListener('keydown', (event) => {
      this.keyStates.set(event.code, true);
    });
    document.addEventListener('keyup', (event) => {
      this.keyStates.set(event.code, false);
    });

    if (!this.container) {
      this.container = document.body;
    }

    this.container.addEventListener('mousedown', () => {
      document.body.requestPointerLock();
    });

    // rotation
    document.body.addEventListener('mousemove', (event) => {
      if (document.pointerLockElement === document.body) {
        camera.rotation.y -= event.movementX / this.rotatefactor;
        camera.rotation.x -= event.movementY / this.rotatefactor;
      }
    });
  }

  private getForwardVector(): Vector3 {
    const playerDirection = new Vector3()

    this.camera.getWorldDirection(playerDirection);
    playerDirection.y = 0;
    playerDirection.normalize();

    return playerDirection;
  }

  private getSideVector(): Vector3 {
    const playerDirection = new Vector3()

    this.camera.getWorldDirection(playerDirection);
    playerDirection.y = 0;
    playerDirection.normalize();
    playerDirection.cross(this.camera.up);

    return playerDirection;
  }

  private playerVelocity = new Vector3();

  private updateVelocity(deltaTime: number) {
    const speedDelta = deltaTime * 8;

    if (this.keyStates.get('KeyW')) {
      this.playerVelocity.add(this.getForwardVector().multiplyScalar(speedDelta));
    }

    if (this.keyStates.get('KeyS')) {
      this.playerVelocity.add(this.getForwardVector().multiplyScalar(-speedDelta));
    }

    if (this.keyStates.get('KeyA')) {
      this.playerVelocity.add(this.getSideVector().multiplyScalar(-speedDelta));
    }

    if (this.keyStates.get('KeyD')) {
      this.playerVelocity.add(this.getSideVector().multiplyScalar(speedDelta));
    }
  }

  private moveCamera(deltaTime: number) {
    // slow after mouse up
    let damping = Math.exp(-3 * deltaTime) - 1;

    this.playerVelocity.addScaledVector(this.playerVelocity, damping);

    const deltaPosition = this.playerVelocity.clone().multiplyScalar(deltaTime);
    if (this.camera) {
      this.camera.position.add(deltaPosition);
      this.camera.position.y = this.viewerheight;
    }
  }

  animate({ delta }: NgtRender) {
    this.updateVelocity(delta*this.movespeed);  // check for input
    this.moveCamera(delta); // move player
  }
}
@IRobot1 IRobot1 changed the title First Person movement code [Feature] First Person movement code Mar 11, 2022
@nartc
Copy link
Owner

nartc commented May 2, 2022

Can we close this issue @IRobot1 ?

@IRobot1
Copy link
Contributor Author

IRobot1 commented May 2, 2022

Yes. This code is in the cannon examples repo if anyone needs a current copy.

@IRobot1 IRobot1 closed this as completed May 2, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants