Need help with constraining player movement speed

Hello, so I am trying to make a top down shooter. I want my player to always move in constant speed, but I can’t figure out how to do it correctly.

I have put a text label with the player’s speed (it should always be at 400), you can try it here https://ogamrima.github.io/index.html
Try moving one way (for example S) and then while holding S try switching between A and D keys and then stop switching and just hold S. You will see that the player keeps slowing down. Is there maybe a better way to move the player?

Also off topic, when I hold A and then while holding A I press D and release, the player keeps going to the right, when only A is pressed, is there a way to fix this?

Here is movement related code:

 class GamePlay extends Phaser.Scene {
  constructor() {
    super({
      key: "GamePlay",
    });
    this.w = 3200;
    this.h = 2400;
    this.speed = 400;
    //...
  }
  preload() {}
  create() {
    this.player = this.physics.add.sprite(this.w / 2, this.h / 2, "player").setScale(0.25);

    this.txt = this.add.text(
      this.cameras.main.scrollX,
      this.cameras.main.scrollY,
      "", {
        font: "25px Arial",
        fill: "yellow",
      }
    );

    this.mouse = this.input.activePointer;

    this.moveKeys = this.input.keyboard.addKeys({
      up: Phaser.Input.Keyboard.KeyCodes.W,
      down: Phaser.Input.Keyboard.KeyCodes.S,
      left: Phaser.Input.Keyboard.KeyCodes.A,
      right: Phaser.Input.Keyboard.KeyCodes.D,
    });

    this.input.keyboard.on("keydown_W", (e) => {
      this.player.setVelocityY(-this.speed);
    });
    this.input.keyboard.on("keydown_S", (e) => {
      this.player.setVelocityY(this.speed);
    });
    this.input.keyboard.on("keydown_A", (e) => {
      this.player.setVelocityX(-this.speed);
    });
    this.input.keyboard.on("keydown_D", (e) => {
      this.player.setVelocityX(this.speed);
    });

    this.input.keyboard.on("keyup_W", (e) => {
      if (this.moveKeys["down"].isUp) {
        this.player.setVelocityY(0);
      }
    });
    this.input.keyboard.on("keyup_S", (e) => {
      if (this.moveKeys["up"].isUp) {
        this.player.setVelocityY(0);
      }
    });
    this.input.keyboard.on("keyup_A", (e) => {
      if (this.moveKeys["right"].isUp) {
        this.player.setVelocityX(0);
      }
    });
    this.input.keyboard.on("keyup_D", (e) => {
      if (this.moveKeys["left"].isUp) {
        this.player.setVelocityX(0);
      }
    });
  }

  constrainVelocity(sprite, maxVelocity) {
    if (!sprite || !sprite.body) return;

    var angle, currVelocitySqr, vx, vy;
    vx = sprite.body.velocity.x;
    vy = sprite.body.velocity.y;
    currVelocitySqr = vx * vx + vy * vy;

    if (currVelocitySqr > maxVelocity * maxVelocity) {
      angle = Math.atan2(vy, vx);
      vx = Math.cos(angle) * maxVelocity;
      vy = Math.sin(angle) * maxVelocity;
      sprite.body.velocity.x = vx;
      sprite.body.velocity.y = vy;
    }
  }

  update(time, delta) {
    this.input.activePointer.updateWorldPoint(this.cameras.main);
    this.mouseX = this.input.activePointer.worldX;
    this.mouseY = this.input.activePointer.worldY;
    this.player.rotation = Phaser.Math.Angle.Between(
      this.player.x,
      this.player.y,
      this.mouseX,
      this.mouseY
    );

    this.constrainVelocity(this.player, this.speed);
    this.txt.text = this.player.body.speed;
    this.txt.setPosition(this.cameras.main.scrollX, this.cameras.main.scrollY);
  }
}

Hi,
Instead of your function constraintVelocity you can try:

this.player.body.velocity.normalize().scale(400);

Not sure if it will works better…

2 Likes

Nice haha :smiley: it works!
and for the off topic question, does it do the same to you?

Also off topic, when I hold A and then while holding A I press D and release, the player keeps going to the right, when only A is pressed, is there a way to fix this?

Yes, because it’s the last pressed key.
I usually use:

if (right.isDown && !left.isDown) {
  // move to the right
}
if (left.isDown && !right.isDown) {
  // move to the left
}
1 Like

Do you think this way is okay performance wise? Or is it the same as the method I used

I don’t know…
But you can get the same result with your way

this.input.keyboard.on("keydown_A", (e) => {
      if (this.moveKeys["right"].isUp) {
          this.player.setVelocityX(-this.speed);
      }
    });
1 Like