How can I normalize my diagonal movement with this algorithm (ignore the texture thing)

I’m starting in monogame coding, so sorry if this sounds a bit noob, but I made this algorithm to move in 8 directions that is a bit diferent so I can’t normalize it by the normal way.
Any tips?

public Vector2 _velocity;
        public Vector2 dir;
        public int hsp, vsp, spd = 4;

        public Player(Texture2D sprite)
        {
            _spritesheet = sprite;
            _velocity = new Vector2();
        }

        public override void Update()
        {

            KeyboardState keyboard = Keyboard.GetState();

            int right = Convert.ToInt32(keyboard.IsKeyDown(Keys.D)),
                left = Convert.ToInt32(keyboard.IsKeyDown(Keys.A)),
                up = Convert.ToInt32(keyboard.IsKeyDown(Keys.W)),
                down = Convert.ToInt32(keyboard.IsKeyDown(Keys.S));

            var mag = (right - left != 0) || (down - up != 0);
            dir = new Vector2((right - left), (down - up));

            _velocity += dir * spd;

            _position = _velocity;
        }

if (dir != Vector2.Zero) dir.Normalize();

What’s mag for?

1 Like

Thank you. I was trying to do it by myself before, i was trying to convert a method wich I use in gamemaker:

up = keyboard_check(ord("W"));
down = keyboard_check(ord("S"));
right = keyboard_check(ord("D"));
left = keyboard_check(ord("A"));

input_dir = point_direction(0, 0, (right - left), (down - up));
input_mag = ((right - left) != 0) or ((down - up) != 0);

hsp = lengthdir_x(input_mag * spd, input_dir);
vsp = lengthdir_y(input_mag * spd, input_dir);

x += hsp;
y += vsp;

hspeed and vspeed are Velocity.X and Velocity.Y.

The Convert.ToInt32(keyboard.IsKeyDown(Keys.D)) is converting True and False to Int32, probably not what you intended.

Lets simplify your code:


//(X,Y)
public float _position;
//(hspeed,vspeed)
public Vector2 _velocity;
public float _spd;  


// Direction in radians
public  float Direction {get { return (float)Math.Atan2(-_velocity.Y, _velocity.X);} set {_velocity = new Vector2((float)Math.Cos(value),(float)Math.Sin(value)) * _spd}};

// Speed 
public float Speed { get {return _spd;} set {_spd = value; if(_velocity.LengthSquared() > 0.0001f) { _velocity.Normalize(); velocity * = value;}}};

// .... skip to Update...

   KeyboardState keyboard = Keyboard.GetState();
// stop on release
   _velocity = Vector2.Zero;

   if(keyboard.IsKeyDown(Keys.D)) _velocity.X = 1; 
// actual values do not matter here just as long as they are the same magnitude.
   if(keyboard.IsKeyDown(Keys.A)) _velocity.X = -1;

   if(keyboard.IsKeyDown(Keys.S)) _velocity.Y = 1;
   if(keyboard.IsKeyDown(Keys.W)) _velocity.Y = -1;

   if(_velocity.LengthSquared() > 0.0001f)  // if velocity is zero, the normalize will return NaN and cause the draw not to function.
   {
       _velocity.Normalize();
       _velocity *= _spd;
      _position += _velocity;
   }

I hope this helps.

1 Like

Be careful with float and Vector2 equality. Some values cannot be expressed perfectly and require a ± float.Epsilon range for each axis, Attempting a Normalize() a value where components are non-zero and distance squared < float.Epsilon, Vector2.Normalize() will result in a division by 0 and NaN propagation for all further calculations.