applyForce and lookAt used together causing weird issues

Hello. Just trying to develop a simple top down space shooting game like asteroids… You can use WASD to move the spaceship, and the mouse will focus the aim of the spaceship.

I am using rigidbody applyForce successfully, but I can only seem to use lookAt when the entity is not moving… That means either at the start of the game, or after it has stopped moving… Here is the project, and the code.

https://playcanvas.com/project/551352/

The ShipController (works fine)


var ShipController = pc.createScript('shipController');

/**
 * Initialize
 * @returns {ShipController}
 */
ShipController.prototype.initialize = function() {    
    // properties
    this.forwardSpeed = 9.8;
    this.backwardSpeed = 9.8;
    this.strafeLeftSpeed = 9.8;
    this.strafeRightSpeed = 9.8;
    this.pitchUpSpeed = 0;
    this.pitchDownSpeed = 0;
    this.yawLeftSpeed = 3;
    this.yawRightSpeed = 3;
    this.rollLeftSpeed = 3;
    this.rollRightSpeed = 3;
    
    this.app.keyboard.on(pc.EVENT_KEYDOWN, this.onKeyDown, this);
    this.app.keyboard.on(pc.EVENT_KEYUP, this.onKeyUp, this);    
    return this;
};

/**
 * Update
 * @returns {ShipController}
 */
ShipController.prototype.update = function(dt) {
    if (pc.app.keyboard.isPressed(pc.KEY_LEFT) || pc.app.keyboard.isPressed(pc.KEY_A)) {
        this.strafeLeft();
    }
    if (pc.app.keyboard.isPressed(pc.KEY_RIGHT) || pc.app.keyboard.isPressed(pc.KEY_D)) {
        this.strafeRight();
    }
    if (pc.app.keyboard.isPressed(pc.KEY_UP) || pc.app.keyboard.isPressed(pc.KEY_W)) {
        this.moveForward();
    }
    if (pc.app.keyboard.isPressed(pc.KEY_DOWN) || pc.app.keyboard.isPressed(pc.KEY_S)) {
        this.moveBackward();
    }
    
    return this;
};

/**
 * Move forward (x axis)
 * @returns {ShipController}
 */
ShipController.prototype.moveForward = function (event) {
    this.entity.rigidbody.applyForce(this.forwardSpeed, 0, 0);
    return this;
};

/**
 * Move backward (x axis)
 * @returns {ShipController}
 */
ShipController.prototype.moveBackward = function (event) {
    this.entity.rigidbody.applyForce(this.backwardSpeed * -1, 0, 0);
    return this;
};

/**
 * Strafe right (z axis)
 * @returns {ShipController}
 */
ShipController.prototype.strafeRight = function (event) {
    this.entity.rigidbody.applyForce(0, 0, this.strafeRightSpeed);
    return this;
};

/**
 * Strafe left (z axis)
 * @returns {ShipController}
 */
ShipController.prototype.strafeLeft = function (event) {
    this.entity.rigidbody.applyForce(0, 0, this.strafeLeftSpeed * -1);
    return this;
};

/**
 * Event handler called when key is pressed
 * @returns {ShipController}
 */
ShipController.prototype.onKeyDown = function (event) {
    //event.event.preventDefault();
    return this;
};

The mouse controller (only works when entity is not moving…! and even then, flips the entity the wrong way)


var FollowMouse = pc.createScript('followMouse');

/**
 * Initialize
 * @returns {FollowMouse}
 */
FollowMouse.prototype.initialize = function() {
    this.cameraEntity = this.app.root.findByName('Camera');
    this.mousePosition = new pc.Vec3();
    this.mouseScreenPosition = new pc.Vec3();
    this.app.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
    return this;
};

/**
 * Update
 * @param {number} dt
 * @returns {FollowMouse}
 */
FollowMouse.prototype.update = function(dt) {
    if(this.cameraEntity){
        this.cameraEntity.camera.screenToWorld(this.mouseScreenPosition.x, this.mouseScreenPosition.y, this.cameraEntity.getPosition().y, this.mousePosition);   
    }
    
    this.mousePosition.y = this.entity.getPosition().y; 
    this.entity.lookAt(this.mousePosition);
    return this;
};

/**
 * Mouse move handler
 * @param {object} event - mouse event 
 * @returns {FollowMouse}
 */
FollowMouse.prototype.onMouseMove = function (event) {
    this.mouseScreenPosition.x = event.x;
    this.mouseScreenPosition.y = event.y;
    return this;
};

I am stumped.

If you are using rigid body on an entity, you can’t use lookAt as the physics simulation ‘overwrites’ the rotation and positio of the entity.

To rotate a rigid body, use applyTorque.

1 Like

Oh wow I see. How will I calculate the angle to rotate based on the position of the mouse? I feel like its a common function and possibly is built in?

Also I don’t exactly want to apply torque… I want the entity to always be looking at the mouse. Really I’m just trying to replicate Asteroids, but the ship is always pointing at the mouse.

This is the exact control I’m trying to do !

You can do it another way. As along as the collision shape is the same no matter the orientation (ie a sphere), you can separate the visual representation from the rigid body. If the main entity contains the rigid body, you can add a child entity that has the render/model and make the child look at where the mouse is at all times.

Just make sure that you set the rigid body params so it can’t rotate.

1 Like

Thank you. I finally have it working.

1 Like