Having difficulty controlling the movement of my object with an onscreen joystick (nipplejs) using three js and ammo js

Currently, I am working on an open-world project using three.js along with the ammo.js physics engine. After completing all the necessary setup and ensuring that collisions are functioning correctly, I encountered a particular issue. Despite my efforts, I am finding it challenging to move the specific object I intend to control using a joystick (utilizing nipple.js). Below you will find the code snippet related to both the object creation and the joystick controls.

function createPlayer() { 
 let pos = {x: 0, y: 0, z: 0};
 let quat = {x: 0, y: 0, z: 0, w: 1};
 let scale = {x: 5, y: 10, z: 5};
 let mass = 0;
 let player = new THREE.Mesh(new THREE.BoxBufferGeometry(), new THREE.MeshBasicMaterial({color: 0x2d2d2d,
 }));
scene.add( player );
player.scale.set(scale.x,scale.y,scale.z);
player.position.set(0,5,0);
player.castShadow = true;
player.receiveShadow = true;

 scene.add(player); 
let transform = new Ammo.btTransform();
                transform.setIdentity();
                transform.setOrigin( new Ammo.btVector3( pos.x, pos.y, pos.z ) );
                transform.setRotation( new Ammo.btQuaternion( quat.x, quat.y, quat.z, quat.w ) );
                let motionState = new Ammo.btDefaultMotionState( transform );

                let colShape = new Ammo.btBoxShape( new Ammo.btVector3( scale.x , scale.y , scale.z  ) );
                colShape.setMargin( 0.05 );

                let localInertia = new Ammo.btVector3( 0, 0, 0 );
                colShape.calculateLocalInertia( mass, localInertia );

                let rbInfo = new Ammo.btRigidBodyConstructionInfo( mass, motionState, colShape, localInertia );
                let body = new Ammo.btRigidBody( rbInfo );


                
                physicsWorld.addRigidBody( body, colGroupPlane, colGroupRedBall );
                
                
let fwdValue = 0;
let bkdValue = 0;
let rgtValue = 0;
let lftValue = 0;
let tempVector = new THREE.Vector3();
let upVector = new THREE.Vector3(0, 1, 0);
let joyManager;

function updatePlayer(){
  // move the player
  const angle = controls.getAzimuthalAngle()
  
    if (fwdValue > 0) {
        tempVector
          .set(0, 0, -fwdValue)
          .applyAxisAngle(upVector, angle)
        player.position.addScaledVector(
          tempVector,
          1
        )
      }
  
      if (bkdValue > 0) {
        tempVector
          .set(0, 0, bkdValue)
          .applyAxisAngle(upVector, angle)
        player.position.addScaledVector(
          tempVector,
          1
        )
      }

      if (lftValue > 0) {
        tempVector
          .set(-lftValue, 0, 0)
          .applyAxisAngle(upVector, angle)
        player.position.addScaledVector(
          tempVector,
          1
        )
      }

      if (rgtValue > 0) {
        tempVector
          .set(rgtValue, 0, 0)
          .applyAxisAngle(upVector, angle)
        player.position.addScaledVector(
          tempVector,
          1
        )
      }
  
  player.updateMatrixWorld()
  
  //controls.target.set( mesh.position.x, mesh.position.y, mesh.position.z );
  // reposition camera
  camera.position.sub(controls.target)
  controls.target.copy(player.position)
  camera.position.add(player.position)
 
}

function addJoystick(){
   const options = {
        zone: document.getElementById('joystickWrapper1'),
        size: 120,
        multitouch: true,
        maxNumberOfNipples: 2,
        mode: 'static',
        restJoystick: true,
        shape: 'circle',
        // position: { top: 20, left: 20 },
        position: { top: '0', left: '0' },
        dynamicPage: true,
      }
   
   
  joyManager = nipplejs.create(options);
  
joyManager['0'].on('move', function (evt, data) {
        const forward = data.vector.y
        const turn = data.vector.x

        if (forward > 0) {
          fwdValue = Math.abs(forward)
          bkdValue = 0
        } else if (forward < 0) {
          fwdValue = 0
          bkdValue = Math.abs(forward)
        }

        if (turn > 0) {
          lftValue = 0
          rgtValue = Math.abs(turn)
        } else if (turn < 0) {
          lftValue = Math.abs(turn)
          rgtValue = 0
        }
      })

     joyManager['0'].on('end', function (evt) {
        bkdValue = 0
        fwdValue = 0
        lftValue = 0
        rgtValue = 0
      })
  
}
addJoystick();
            }
            

Answer №1

When using Ammo.js for player-controlled movement, I discovered that setting a Linear Velocity explicitly was more effective than trying to update the position directly.

For an example, check out this answer:

You could also introduce another level of abstraction by applying a force (leading to acceleration, velocity changes, and ultimately position updates) instead of directly controlling velocity or position.

From my experience, working with forces and velocities is generally simpler when utilizing a physics engine compared to manually setting object positions.

However, if you do prefer setting the position directly, you may find this answer helpful as well:

Answer №2

Employing the set linear velocity method to propel the object in this particular scenario involves directly obtaining input from a joystick and utilizing it to drive the motion of a spherical ball.

let fwdValue = 0;

let bkdValue = 0;

let rgtValue = 0;

let lftValue = 0;

function moveBall() {

  let scalingFactor = 6;
  
  let moveX = rgtValue - lftValue;
  let moveZ = bkdValue - fwdValue;
  let moveY = 0;

  if (moveX == 0 && moveY == 0 && moveZ == 0) return;

  let resultantImpulse = new Ammo.btVector3(moveX, moveY, moveZ)
  resultantImpulse.op_mul(scalingFactor);

  let physicsBody = ballObject.userData.physicsBody;
  physicsBody.setLinearVelocity(resultantImpulse);

}

Issue resolved successfully ✔️

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

Improving JavaScript function by restructuring and eliminating conditional statements from within a loop

Looking for advice on how to refactor my function and eliminate the if statement inside the loop. Any suggestions would be helpful as I suspect the else condition is unnecessary. function quantitySum(array) { let sum = 0; for (let i = 0; i < array ...

Ways to navigate a div within an iframe that has been loaded

As I load a page(A) inside an iframe, the HTML structure of the embedded content is as follows: <html><body> <div id="div1"></div> <div id="div2"><button>Hello</button></div> </body></html> The ...

Utilizing Method-Override with a PUT request

Within my app.js file, I included the method-override module and utilized app.use(methodOverride("_method")) However, An issue arose indicating that the error message did not contain the ?_method=PUT parameter in the URL. This snippet is a portion of my ...

What is the best way to send a parameter to a mousewheel event?

for (var i = 0; i < 10; i++) { $('#content-scroll' + i).mousewheel(function(event, delta) { if (delta > 0) sliderUp(i - 1); else if (delta < 0) sliderDown(i - 1); return false; // prevent default }); } I am facing an iss ...

JavaScript: Modifying the Style of a :lang Selector

Currently, I am working on creating a basic multilingual static website using only HTML5, CSS3, and vanilla JavaScript. The structure of the HTML looks something like this: <html> <head> <title>WEBSITE</title> ...

When context.getImgData() is invoked, it triggers a noticeable flickering effect on the canvas

Currently, I am integrating a webcam feed into a video element and then projecting it onto a canvas element. Subsequently, I am implementing face detection on the canvas to highlight faces with a square. The issue at hand arises when I call the context.ge ...

What is the best way to display multiple modals in a React app?

I am facing a challenge where I need to render multiple modals based on the number of items in the 'audios' property of an object. Currently, I am using the mui modal library for this functionality. Here are the variables being utilized: const ...

Utilize String to Set Cookies

My goal is to utilize requestjs for making requests and sharing cookies across various JavaScript files and servers. To achieve this, I have chosen to store the cookies in a database as a string and retrieve them when necessary. The string format aligns w ...

The WebGL rendering is failing to load due to a lost context error

I have a 3D model of a road, available both with and without textures. When I load the road without textures, everything runs smoothly at around 60fps. However, when I load the textured version of the road, two different scenarios occur: 1) If the 3D mod ...

Incorporate imagesloaded.js into your PHP script to seamlessly import images from a designated folder

I've implemented the code below into a bootstrap modal to display images from a website folder. These images are loaded using lazyload.js when the modal is opened. Sometimes, there's a delay in displaying images depending on their sizes. I'd ...

A guide on shading specific faces based on their normal vectors' alignment with the camera's view

https://i.sstatic.net/FG4hp.png I'm currently working on a shader that requires darkening the faces with normals perpendicular to the camera (dot product is 0). How can I calculate this dot product and make sure it works correctly? uniform float tim ...

How can I utilize module imports with the support of web browsers?

I'm currently troubleshooting why my script tags are not functioning in my html file. I discovered an article mentioning the ability to import modules into browsers using a script tag with a module type. The information was found on this site: https:/ ...

What is the reason behind getElementsByClassName not functioning while getElementById is working perfectly?

The initial code snippet is not functioning correctly DN.onkeyup = DN.onkeypress = function(){ var div = document.getElementById("DN").value document.document.getElementsByClassName("options-parameters-input").style.fontSize = div; } #one{ heigh ...

The data retrieved from the Redis cache does not have pagination implemented

After incorporating Redis cache into my backend API, I encountered an issue where pagination no longer worked on both the backend and frontend. Here is a snippet of the middleware that executes before retrieving all data: const checkCache = (req, res, next ...

Encountered an error while attempting a server-side fetch with NextJS - TypeError: Unable to parse the URL from the address httр://localhost

I encountered an issue while trying to retrieve data from another resource using an API endpoint in NextJS (development mode). The error message I received is as follows: Error - TypeError: Failed to parse URL from httр://localhost:3000/api/test at Ob ...

Guide to adding information to an .xml document

Currently, I am working on building a website for a school project, specifically an online shop. I am focusing on the shop section, where I need to store data such as name, price, image, and description in either a text file or XML format. Right now, the w ...

WooCommerce - Custom button feature for canvas art and paintings. [Coding in PHP, Javascript, HTML, and CSS]

I am in need of a plugin or function that can create a pop-up modal displaying size information for paintings on WooCommerce. While there are many options available for showing size charts and tables, I have not been able to find one specifically designed ...

The PHP Comet feature is causing the page to experience delays in reloading

Hello, I am working on implementing comet functionality using PHP and jQuery. The comet starts with every page load, but this seems to be causing a significant delay in loading any page on the website, taking about 10 seconds. It appears as though the page ...

Encountering module error 'internal/fs' after updating to Node 7

We have encountered some challenges after attempting to update our build server to node v7.0.0. Specifically, the application build task fails at the "bower_concat" step with the following error message: Loading "bower-concat.js" tasks...ERROR Error: Cann ...

Upon selecting the display image option

Here is a jsfiddle file provided for your reference. I am attempting to create a functionality where upon clicking buttons (1,2,3,4), the corresponding image shows up and overlaps with any previously displayed images. I have tried using the following code ...