The relationship between Three.js camera and object movement intertwined

As a beginner, I have implemented THREE pointer lock controls and perspective camera for my object. However, when adding both of them to the object, only one gets added based on which one was added first. I'm also facing difficulty in moving the object in the direction of the WASD keys along with rotating it as per the camera angle. Below are the important snippets of code.

The object moves correctly in the North, East, South, West directions, but if I move the camera, it still moves according to its initial direction rather than adjusting to the new angle. For example, if I aim East and move forward, the object goes North.

Additionally, whenever I move in any direction, the object snaps back to the position 0, 0, 0.

 function e() {
    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);

    scene = new THREE.Scene();

    scene.background = new THREE.Color(0xffffff);

    var playerGeometry = new THREE.BoxBufferGeometry(10, 40, 10);
    playerGeometry = playerGeometry.toNonIndexed(); // ensure each face has unique vertices

    var playerMaterial = new THREE.MeshPhongMaterial({
      specular: 0xffffff,
      flatShading: true,
      vertexColors: THREE.VertexColors
    });

    window.player = new THREE.Mesh(playerGeometry, playerMaterial);

    console.log(player);

    window.player.add(camera);
    camera.position.set(0, 20, 20); 
    
     controls = new THREE.PointerLockControls(camera);
     window.player.add(controls.getObject());
    scene.add(player);
    objects.push(player);
    }
    
    
  ========================================================================= // Then the animation, these are just snippets not ofc the whole thing
    
    function animate() {

    requestAnimationFrame(animate);

    if (controls.enabled) {
      raycaster.setFromCamera(direction, camera);

      var time = performance.now();
      var delta = (time - prevTime) / 1000;

      velocity.x -= velocity.x * 10.0 * delta;
      velocity.z -= velocity.z * 10.0 * delta;
      velocity.y -= 3.8 * 100.0 * delta; // 100.0 = mass

      if (window.player.position) {
      window.player.position.z = Number(keys[87]) - Number(keys[83]);
      window.player.position.x = Number(keys[65]) - Number(keys[68]);
      window.player.position.normalize(); // this ensures consistent movements in all directions

      if (keys[87] || keys[83])  window.player.position.z -= window.player.position.z * 400.0 * delta;
      if (keys[65] || keys[68])  window.player.position.x -= window.player.position.x * 400.0 * delta;
      if (keys[32]) velocity.y = 200;
      }
      controls.getObject().translateX(velocity.x * delta);
      controls.getObject().translateY(velocity.y * delta);
      controls.getObject().translateZ(velocity.z * delta);

      if (controls.getObject().position.y < 10) {
        velocity.y = 0;
        controls.getObject().position.y = 10;
        canJump = true;
      }

      prevTime = time;

      if (camControls) camControls.update(delta);
    }

    renderer.render(scene, camera);

  }

Answer №1

By understanding your requirements correctly, achieving the desired camera movement can be done by implementing the following adjustments to your code within the if (window.player.position) block.

The main concept here is updating the camera's position using direction vectors derived from the camera's own direction. This ensures that the camera moves in the right path relative to its current direction:

if (window.player.position) {
/* 
  Avoid this logic

  window.player.position.z = Number(keys[87]) - Number(keys[83]);
  window.player.position.x = Number(keys[65]) - Number(keys[68]);
  window.player.position.normalize(); // this ensures consistent movements in 
  all directions
*/

/* Extract the forward-facing vector from your camera. This provides a vector
   for moving forward relative to the camera's pointing direction */
var forward = new THREE.Vector3()
camera.getWorldDirection(forward)

/* Obtain a vector pointing to the right of the camera's current direction. This gives a vector for left/right movement (strafing)
   based on the camera's direction */
var right = new THREE.Vector3().crossVectors(camera.up, forward)

// Normalize the vectors for consistent camera movement
forward.normalize()
right.normalize()

if (keys[87])  {

  /* Add "velocity" vector to the player's current position, based on
     camera's forward direction */
  window.player.position.addScaledVector(forward, 1.0 * delta); 
}

if (keys[83])  {

  /* Add "velocity" vector to the player's current position, based on 
     camera's backward direction (-1.0) */
  window.player.position.addScaledVector(forward, -1.0 * delta); 
}

if (keys[65]) { 

  /* Add "strafe" vector to the player's current position, based on
     camera's right direction */
  window.player.position.addScaledVector(right, 1.0 * delta);
}

if (keys[68]) { 

  /* Add "strafe" vector to the player's current position, based on
     camera's left direction (-1.0) */
  window.player.position.addScaledVector(right, -1.0 * delta);
}

if (keys[32]) velocity.y = 200;

}

// -- ADD TO ACHIEVE THIRD PERSON CAMERA --

// Temporary vectors storing data for our 3rd person camera behavior
const playerPosition = new THREE.Vector3()
const cameraPosition = new THREE.Vector3()

// Retrieve player and camera positions
window.player.getWorldPosition(playerPosition)
camera.getWorldPosition(cameraPosition)

// Calculate an offset vector for the camera based on the player's
// current position and the current direction from camera to player
const cameraOffset = new THREE.Vector3().subVectors(playerPosition, cameraPosition)

// Set distance between player and third-person view. Adjust 5.0 to bring
// camera closer to player
cameraOffset.setLength(5.0) 

// Calculate new camera positions
const newCameraPosition = new THREE.Vector3().addVectors(playerPosition, cameraOffset)

// Update camera lookat object (player) and position to achieve
// third-person effect
camera.lookAt(playerPosition)
camera.position.copy(newCameraPosition)

I hope this explanation helps you further! :-)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Passing HttpClient from app.module to another module and then to a service in Angular

Currently, I am in the process of developing my own Angular NPM Package with the prefix "ngx-*". I have successfully compiled the package and am now integrating it into a new project by utilizing the npm link command. Within the service, there is a constr ...

Is there a way to efficiently use AJAX and PHP to iterate through JSON data and save it to a new JSON file

I have created a simple movie editor with a sidebar where users can drag and drop elements. On the right side, users can edit these elements as they wish and save the data to a JSON file. When the user clicks save, I want it to create a new file and save t ...

Oops! There was an unexpected error: TypeError - It seems that the property 'title' cannot be read because it is undefined

HTML document example <ion-header> <ion-toolbar color="danger"> <ion-buttons> <button ion-button navPop icon-only> <ion-icon ios="ios-arrow-back" md="md-arrow-back"></ion-icon> </button> ...

Is there a way to eliminate a wrapper object from each element in a JSON array using JavaScript?

My knowledge of JavaScript is limited and I am facing a particular issue. The JSON document at hand looks like this: { "forecast": [ { "day-1": { "forecast_date": "2017-11-23", "morning": { "weather": { " ...

This message is designed to validate the form as it is dynamic and

Is there a way to dynamically determine which .input fields have not been entered yet? In the following code snippet, you can observe that if I input data out of sequence, the #message displays how many inputs have been filled and shows the message in sequ ...

sending information from a PHP form to a JavaScript window

Currently, I am in the process of developing a game using javascript and jquery. In this game, when a player interacts with another character, it triggers the opening of text from an external file using the window.open('') function. At the start ...

Encountering an unexpected token error in React.js

As a new learner of React, I am still getting acquainted with JavaScript. It has been my first week attempting to import React, and finally adding the CDN script tag into my index.html. Normally, I can easily add XML tags into JS files, but when trying to ...

What causes the Woocommerce checkout button to be blocked on the checkout page?

I am perplexed by WooCommerce's decision to block this section of the screen with an overlay. Under what circumstances would it do so? checkout page screenshot ...

Tips for incorporating a hyperlink into a pop-up box

I need some assistance with adding a link to a pop-up window. Here's the HTML code I currently have: HTML <div id="popup"> <a href="#"><div id="popup-headline">News 1</div><div id="local">News Author</div> <di ...

Ways to control the number of boxes that are checked

I am currently working on a script to restrict the number of checkboxes that can be checked, but I am encountering an issue where the script is disabling all checkboxes on the page. Is there a way to only disable a specific checkbox within a certain div? ...

Requesting title elements from an XML page using Ajax response is not functioning correctly

Could someone please help me understand why I am unable to retrieve the elements from an XML document? When I click on the et Title button in the body section, nothing is being displayed. Here's the code snippet: function MyF () { var xml ...

Guide to sending a specialized SPL token using the libraries '@solana/web3.js' and '@solana/sol-wallet-adapter'

Attempting to transfer a custom SPL token using the solana-wallet adapter is proving to be challenging due to difficulty in obtaining the wallet's secret key for signing the transaction. Although I have reviewed resources on writing the transfer code ...

What is the process for adding JSON data to a dropdown menu using PHP AJAX?

I am trying to populate a select html element with data from a list of JSON results. Here is the code I have attempted: JSON output: jquery loop on Json data using $.each {"Eua":"Eua","Ha'apai":"Ha'apai",& ...

The Vue component is only functioning partially and is not visible in the Vue inspector

I have a straightforward Vue component that is causing me some trouble. <template> <div class="field has-addons"> <div class="control is-expanded"> <div class="select is-fullwidth"> <select v-mode ...

Using Sinon with Ember to create a Mock Server

I am looking to test my controller by making an ajax call to my backend using Jasmine and Sinon. To fake my backend server with Sinon, I attempted the following approach: describe("fake server", function() { var server; beforeEach(function() { this ...

What is the best way to convert this jQuery code into an AngularJS implementation?

I'm diving into the world of AngularJS and looking for a more elegant solution using AngularJS principles Controller $scope.filter = function($event, active, id) { var html = ""; if(active){ $http({method: 'GET& ...

Alter the class when $dirty occurs in Angular

I've recently started working with angular js and am attempting to incorporate animations into my login page. I have created a controller that will modify the class of the input field when clicked and when blurred. app.controller("con", function($sc ...

Having Difficulties Initiating Click Actions on Save Buttons Located in Child Components

I'm facing a challenge with triggering click events on save buttons located in child components within my React app. Within my parent component called AddQuestionsPage, I have multiple instances of a child component named Question. Each Question comp ...

Eliminate the commas when listing Google Places types

I am currently utilizing the Google Places API and came across these code snippets at https://developers.google.com/maps/documentation/javascript/examples/place-search-pagination. var map, placesList; function initialize() { var pyrmont = new google.ma ...

What is the best way to incorporate data from my Input field into my Vue.JS application's existing data structure

Struggling with integrating new users into my personal project, particularly in passing input values (userName and userAge) to the parent element for addition to playersData. Here is a sample code snippet from the child component: `<template> <d ...