Diagonal movement (2 keys) causes half-movement

Godot Version

4.3

Question

I have a CharacterBody2D that I’m attempting to move in a tile-based fashion. So instead of moving smoothly, it just moves instantly.

I noticed that when pressing two keys at the same time to “move diagonally” (there are only the 4 cardinal directions programmed) that the CharacterBody2D sprite moves only partially, and not the full amount of pixels, leaving the character in a scuffed location. How do I prevent this behavior? I tried adding _isKeyPressed to no avail. Is there perhaps a way for me to use MoveAndCollide() that is just as snappy as using Position?

Normal pic

Scuffed pic

private bool _isKeyPressed = false;

public override void _PhysicsProcess(double delta)
{
		var direction = Input.GetVector("move_west", "move_east", "move_north", "move_south");
		
		if (Input.IsActionJustPressed("move_north") && !_isKeyPressed)
		{
			_isKeyPressed = true;
			Position += direction * TileSize;
			Input.ActionRelease("move_north");
		}
		
		if (Input.IsActionJustPressed("move_east") && !_isKeyPressed)
		{
			_isKeyPressed = true;
			Position += direction * TileSize;
			Input.ActionRelease("move_east");
		}
		
		if (Input.IsActionJustPressed("move_south") && !_isKeyPressed)
		{
			_isKeyPressed = true;
			Position += direction * TileSize;
			Input.ActionRelease("move_south");
		}
		
		if (Input.IsActionJustPressed("move_west") && !_isKeyPressed)
		{
			_isKeyPressed = true;
			Position += direction * TileSize;
			Input.ActionRelease("move_west");
		}
		
		var screenSize = GetViewportRect().Size;
		// Prevent Player from moving outside of screen.
		Position = new Vector2(
			x: Mathf.Clamp(Position.X, 8, screenSize.X - 16),
			y: Mathf.Clamp(Position.Y, 12, screenSize.Y - 12)
		);
		
		_isKeyPressed = false;
}

You can instead of
if() - if() - if() - if()
make
if() - else if() - else if() - else if()

Or you can read read movement x and y separately, like (in pseudocode)

float _x = 0.0;
float _y = 0.0;

_x = Math.Sign(Input.GetAxis("move_west", "move_east"));
if (_x == 0.0) {
  _y = Math.Sign(Input.GetAxis("move_north", "move_south"));
}

var direction = new Vector2(_x, _y);

and direction can be (0, 0), (-1, 0), (0, -1), (1, 0), (0, 1)

1 Like

You make direction from keys and still use ActionJustPresed to all directions

	var direction = Input.GetVector("move_west", "move_east", "move_north", "move_south");

I think you can remove direction because allow values between 0 and 1, alternative you cast to integer vector (Vector2I) to remove fractions but can require more work.

in East you can use Vector2.Right instead direction

		if (Input.IsActionJustPressed("move_east") && !_isKeyPressed)
		{
			_isKeyPressed = true;
			Position += Vector2.Right * TileSize;
			Input.ActionRelease("move_east");

Optional you can optimize Vector2.Right * TileSize with constant or class variable like

private Vector2 directionEast =  Vector2.Right * TileSize;
		if (Input.IsActionJustPressed("move_east") && !_isKeyPressed)
		{
			_isKeyPressed = true;
			Position += directionEast;
			Input.ActionRelease("move_east");

is no big deal here
if()
position =+ 1
if()
Position =- 1

move(Position)
if both true move 0 can be intended.
bur right he will no needed variable _isKeyPressed = true;

Try

public override void _PhysicsProcess(double delta)
{
    Vector2 direction = Vector2.Zero;

    if (Input.IsActionJustPressed("move_north"))
        direction = Vector2.Up;
    else if (Input.IsActionJustPressed("move_east"))
        direction = Vector2.Right;
    else if (Input.IsActionJustPressed("move_south"))
        direction = Vector2.Down;
    else if (Input.IsActionJustPressed("move_west"))
        direction = Vector2.Left;

    Position += direction * TileSize;

    var screenSize = GetViewportRect().Size;
    // Prevent Player from moving outside of screen.
    Position = new Vector2(
        Mathf.Clamp(Position.X, 8, screenSize.X - 16),
        Mathf.Clamp(Position.Y, 12, screenSize.Y - 12)
    );
}

For some reason my code was visually slowing down the character movement. With this block of code I could feel the character movement was much quicker. I think whatever was causing the slowdown in my application code is the reason for 2 keys to be able to be pressed at the same time. Thanks for your solution!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.