Collider, prevent target to move when source stop move

I’m trying to manage the collision between two elements. The first one is controlled by the directional arrows. I would like the first element to be able to push the second one, similar to a game like “Sokoban.”

When I define a collision between two elements, the second element continues to move even when the first one stops. How can I make the second element stop moving when the first one stops?

I tried doing it like this:

this.physics.add.collider(this.character, this.target, () => {
    this.target.setVelocity(0, 0)
})

It seems to work, but the movement of the character is slowed down.

Here is a sandbox with what I already try:
https://phaser.io/sandbox/vdRQk6Gc

Or here is the code

class MainScene extends Phaser.Scene {

    constructor() {
        super({ key: "MainScene" });
        this.speed = 800
    }

    preload() {
    }

    create() {
        this.character  = this.physics.add.sprite( 500, 16, 'square');
        this.target  = this.physics.add.sprite( 300, 96, 'square');
        this.target.setCollideWorldBounds(true)
        this.character.setCollideWorldBounds(true)
        this.physics.add.collider(this.character, this.target, () => {
            this.target.setVelocity(0, 0)
        })
    }

    update(time, delta) {
        const cursors = this.input.keyboard?.createCursorKeys();
        const calculateSpeed = this.speed / delta * 10;
        if (cursors.left.isDown) {
            this.character.setVelocityX(-calculateSpeed);
            this.character.setVelocityY(0);
            this.lastDirection = "left"
        } else if (cursors.right.isDown) {
            this.character.setVelocityX(calculateSpeed);
            this.character.setVelocityY(0);
            this.lastDirection = "right"
        } else if (cursors.up.isDown) {
            this.character.setVelocityY(-calculateSpeed);
            this.character.setVelocityX(0);
            this.lastDirection = "up"
        } else if (cursors.down.isDown) {
            this.character.setVelocityY(calculateSpeed);
            this.character.setVelocityX(0);
            this.lastDirection = "down"
        } else {
            this.character.setVelocityX(0);
            this.character.setVelocityY(0);
        }
    }

}

const game = new Phaser.Game({
    type: Phaser.AUTO,
    width: 800,
    height: 800,
    backgroundColor: '#111111',
    physics: {
        default: 'arcade',
        arcade: {
          gravity: { x: 0, y: 0 },
          debug: true
        }
    },
    scale: {
        mode: Phaser.Scale.FIT,
        autoCenter: Phaser.Scale.CENTER_BOTH
    },
    scene: [ MainScene ]
})
this.target.body.setSlideFactor(0)

Also, create the cursor keys only once, in create():

this.cursors = this.input.keyboard.createCursorKeys();

Arcade Physics velocities should be constant:

this.character.setVelocityX(-500)
1 Like

Thanks @samme that’s what im l’ooking for, thank’s for your answer and improvement suggestion.

slideFactor work but the movement of the character still slowed down.

How do you prevent the character’s movement from slowing down when it collides with the target?

I don’t undersant this point “Arcade Physics velocities should be constant”

Actually i made this

const calculateSpeed = this.speed / delta * 10;
this.character.setVelocityY(calculateSpeed);

Because if i use a constant value the speed movement change depending on frame rate.
So naively I made a workaround by calculating the velocity dynamically based on the “delta”. But it’s probably not the right solution.

What’s the best way to prevent the speed of the character’s movement from changing due to the frame rate?

Velocities are in pixels per second so the frame rate doesn’t matter. The physics engine is already handling the time delta.