Diagonal Movement speed issue

I’m making a top down game and am trying to implement movement. My characters diagonal movement is faster than their up, down, left, or right movement. Does anyone know how I fix this? I would like my character to move at the same speed regardless of the direction. These are the relevant part of the update and create functions.

  update(time, delta) {
    this.player.body.setVelocity(0);
 
    // Horizontal movement
    if (this.cursors.left.isDown)
    {
        this.player.body.setVelocityX(-100);
    }
    else if (this.cursors.right.isDown)
    {
        this.player.body.setVelocityX(100);
    }

    // Vertical movement
    if (this.cursors.up.isDown)
    {
        this.player.body.setVelocityY(-100);
    }
    else if (this.cursors.down.isDown)
    {
        this.player.body.setVelocityY(100);
    }  
}

  create() {

    this.player = this.physics.add.sprite(100, 300, 'player', 0)

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

https://phaser.io/examples/v3/view/physics/arcade/max-speed

1 Like

I’ve found out a way to do it. Probably not the best or most efficient but it works!

I don’t think samme’s example was quite what I was looking for, but thanks for the link.

In my update function, I’ve simply included a few new if statements for diagonal movement. I’ve made a variable called “speed” which is 100, and made another called “speedDiag” and set it too speed * (1/1.44). This equals about 69.4. The result is movement at the same speed in all directions:

// Diagonal movement
// Up and left
if (this.cursors.left.isDown && this.cursors.up.isDown)
{
    this.player.body.setVelocityX(-speedDiag);
    this.player.body.setVelocityY(-speedDiag);
}

// Up and right
if (this.cursors.right.isDown && this.cursors.up.isDown)
{
    this.player.body.setVelocityX(speedDiag);
    this.player.body.setVelocityY(-speedDiag);
}

// Down and right
if (this.cursors.right.isDown && this.cursors.down.isDown)
{
    this.player.body.setVelocityX(speedDiag);
    this.player.body.setVelocityY(speedDiag);
}

// Down and left
if (this.cursors.left.isDown && this.cursors.down.isDown)
{
    this.player.body.setVelocityX(-speedDiag);
    this.player.body.setVelocityY(speedDiag);
}

Hi, I am well aware that this issue has already been resolved.

This issue, a frequent occurrence in game development, can be addressed by normalizing the player’s velocity. We first calculate the magnitude of the player’s velocity vector. Next, we find the unit vectors for both the horizontal and vertical components of the velocity vector. This method is known as normalization.

/**
   * Calculates the magnitude of the vector.
   *
   * @param {number} x - The horizontal component of the vector.
   * @param {number} y - The vertical component of the vector.
   * @return {number} The magnitude of the vector.
   */
  static getMagnitude(x, y) {
    return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
  }

  /**
   * Checks if any of the vector components are non-zero.
   *
   * @param {number} x - The horizontal component of the vector.
   * @param {number} y - The vertical component of the vector.
   * @return {boolean} The result of the check.
   */
  static checkNonZeroComponents(x, y) {
    return Math.abs(x) > 0 || Math.abs(y) > 0;
  }

  /**
   * Calculates the normalized velocity vector.
   *
   * @param {number} x - The horizontal component of the vector.
   * @param {number} y - The vertical component of the vector.
   * @return {number} The normalized velocity vector.
   */
  static getNormalization(x, y) {
    return this.checkNonZeroComponents(x, y) ? 1 / this.getMagnitude(x, y) : 0;
  }

Then in the Player class, we calculate the unit vectors:

class Player extends Phaser.GameObjects.Ellipse {
  // Your other code goes here...

/**
   * Updates the Player.
   *
   * @param {Object} keys - The keyboard input.
   * @param {Object} cursors - The arrow keys.
   * @param {Object} mouse - The mouse input.
   * @param {number} time - The time elapsed.
   * @return {void} Nothing is returned.
   */
  update(keys) {
    let dx = 0;
    let dy = 0;

    if (keys.left.isDown) {
      dx = -1;
    } else if (keys.right.isDown) {
      dx = 1;
    }

    if (keys.up.isDown {
      dy = -1;
    } else if (keys.down.isDown) {
      dy = 1;
    }

    const normalization = Utility.getNormalization(dx, dy);

    this.body.setVelocityX(this.speed * dx * normalization);
    this.body.setVelocityY(this.speed * dy * normalization);
}

Keep in mind that the variables, dx and dy, represent the direction. We then multiply these by the unit vector (normalization) and scale the resultant vector by the speed to achieve the desired velocity. I hope this helps!

1 Like
this.body.velocity.set(1, 1).setLength(100);
// { x: 70.7…, y: 70.7… }

etc.