How to apply a force forward depending of the camera

Hi,
i am trying to apply force to ball with keyboard (using cannon js), making simple code

Blockquote
let forceX: number = speed * this.dir.lr; //left or right button in my case it’s AD value -1 or 1
let forceZ: number = speed * this.dir.ud; //up or down button in my case it’s WS value -1 or 1
this.body.force.set(forceX, 0, forceZ);

mesh.position.copy(this.body.position as any);
mesh.quaternion.copy(this.body.quaternion as any);

but this code working only if camera not moving rotation.y = 0, i need this code will work with camera rotation no matter on camera rotation but button “down S” ball must moving to camera

i found this code for unity and it working great

Blockquote
Vector3 vec = new Vector3(Input.GetAxis(“Horizontal”), 0, Input.GetAxis(“Vertical”));
vec = Camera.main.transform.TransformDirection(vec.x, 0, vec.z);
Vector3 force = vec.normalized * 8;
GetComponent().AddForce(force);

can you help me pls… sorry for English

You can try using Camera.getWorldDirection. It returns a normalized vector pointing in the same direction as the camera (away from the camera.) You can scale it to your speed and apply directly to the body:

const cameraDirection = camera.getWorldDirection().multiplyScalar(speed);
body.force.set(cameraDirection.x, 0, cameraDirection.z);

I never used cannon, so I assume code for applying force you pasted works as you’d expect, except for direction.

hi thanks for answer, but ball just moving forward where camera look, without any key pressed.
but i need to control him with WASD

let forceX: number = speed * this.dir.lr; //left or right button in my case it’s AD value -1 or 1
let forceZ: number = speed * this.dir.ud; //up or down button in my case it’s WS value -1 or 1

That depends on the rest of your code - I just wrote an example.

// Move ball forward (multiply by -1 * speed to move backwards)
const cameraDirection = camera.getWorldDirection().multiplyScalar(speed);
body.force.set(cameraDirection.x, 0, cameraDirection.z);

// Move to the right (multiply by -1 * speed to move to the left)
const cameraSideways = new Vector3(cameraDirection.z, 0, -cameraDirection.x).multiplyScalar(speed);
body.force.set(cameraSideways.x, 0, cameraSideways.z);

(short explanation)

i making simple example and implement your code

if press A or D nothing happens cuz dir.ud = 0

Si garçon - once again it’s an example, not a copy-paste-‘n-go solution. :’)

If you use it with your code directly, first vector is zeroed anytime you try to move sideways, since your events allow only one keypress at the time - and since sideways vector is calculated from the values of the forward vector, both end up zeroed whenever you try to move sideways. :slight_smile:

Storing the direction vector in a variable before calculations should do the trick:

var cameraDirection = camera.getWorldDirection();
var cameraForward = new THREE.Vector3(cameraDirection.x, 0, cameraDirection.z).multiplyScalar(speed * dir.ud);
cube.position.x += cameraForward.x;
cube.position.z += cameraForward.z;
  
var cameraSideways = new THREE.Vector3(cameraDirection.z, 0, -cameraDirection.x).multiplyScalar(speed * dir.lr);
cube.position.x += cameraSideways.x;
cube.position.z += cameraSideways.z;
2 Likes

Thanks a lot it’s working like i need here is a code what i get

Blockquote
let cameraDirection: THREE.Vector3 = new THREE.Vector3();

    camera.getWorldDirection(cameraDirection);

    // Move ball forward (multiply by -1 * speed to move backwards)

    let cameraForward: THREE.Vector3 = new THREE.Vector3(cameraDirection.x, 0, cameraDirection.z).multiplyScalar(this.speed * this.dir.ud);

    this.body.applyForce(cameraForward as any, this.body.position);

    // Move to the right (multiply by -1 * speed to move to the left)

    let cameraSideways: THREE.Vector3 = new THREE.Vector3(cameraDirection.z, 0, -cameraDirection.x).multiplyScalar(this.speed * -this.dir.lr);

    this.body.applyForce(cameraSideways as any, this.body.position);

Blockquote

You are my HERO!! :slight_smile: