mikewesthad / phaser-matter-collision-plugin

A plugin for making it easier to manage collisions with Phaser 3 + Matter.js
MIT License
99 stars 8 forks source link

[Question] Can't apply force to body on collision detection #5

Closed alrdebugne closed 3 years ago

alrdebugne commented 3 years ago

Hi Mike,

First off, many thanks for your plugin and your series of tutorials. I'm dabbling with game development during lockdown, and my initiation was made much easier through the resources you've put out here.

I don't manage to use applyForce on a body after its collision has been detected by a scene.matterCollision.addOnCollideActive event. The collision is detected, but bodyB (the object I want to apply a force to) doesn't register the force.

Here's my code:

export class SwingState extends State {
    enter(scene, player) {
        const sprite = player.sprite;
        this.swordHitbox = (player.direction === 'left') ? player.hitboxes.swordLeft : player.hitboxes.swordRight;
        // ^ check left or right hitbox, depending on direction in which player is facing
        this.swingForce = 0.1;
        this.swingAngle = 30;

        sprite.setVelocityX(0);
        sprite.anims.play(`swing-${player.direction}`);

        // Check for collision with sword hitbox
        scene.matterCollision.addOnCollideActive({
            objectA: this.swordHitbox,
            objectB: scene.bomb,
            callback: this.hitWithSword,
            context: this
        });

        sprite.once('animationcomplete', () => {
            // Stop tracking collision
            scene.matterCollision.removeOnCollideActive({
                objectA: this.swordHitbox,
                objectB: scene.bomb,
                callback: this.hitWithSword,
                context: this
            });
            this.stateMachine.transition('idle');  // return to idle state
        });
    }
    hitWithSword({ bodyA, gameObjectA, bodyB, gameObjectB, pair }) {
        gameObjectB.applyForce({
            x: Math.cos(this.swingAngle) * this.swingForce,
            y: Math.sin(this.swingAngle) * this.swingForce
        });
    }
}

Could you help me understand what I'm doing wrong?

alrdebugne commented 3 years ago

Hi again, found the source of my problem: matter clears events after they're emitted, so forces aren't applied (see https://github.com/liabru/matter-js/issues/134). Instead, forces have to be applied through a separate call with beforeupdate, such as

scene.matter.world.on('beforeupdate', myFunction, this);

Closing this issue; hope this can help future users.

mikewesthad commented 3 years ago

@alrdebugne shoot, sorry I missed this. I took a break from things over the holidays. Glad you discovered the root of the issue and documented it here. I'll add a note to the readme to help folks who might also hit this issue.