Accuracy vs flow, 2d top-down diagonal movement.

How do you guys handle diagonal movement in 2d games, where the movement is not tile based?

Technically speaking, currently in my game when you walk diagonally in any direction you are traveling faster than if you just move straight up/down/left/right (Because you are moving X and Y += Speed*delta basically). The result is, is takes the same amount of time to travel from one corner of a tile to the opposite corner as it does to travel from one side to the opposite side.

Well, for game flow, this still appears like fluid, natural movement. The character doesnt look like hes moving faster when he travels diagonally, but he is technically covering more ground.

There are many solutions to this, most of them are basically various ways of dividing the movement speed by the sqrt2, this results in much more accurate travel distance from point A to B. But, from a player’s perspective the character feels like he’s slowing down substantially when you move diagonally, it just doesn’t feel natural anymore.

From playing a few old top down games that allow free flowing diagonal movement, It looks to me like they don’t care about the discrepancy either unless they have a magical way of hiding it, their diagonal movement appears like mine. It’s just X and Y += Speed*delta.

I was hoping to get some more input on the situation, because I can’t find a solid answer anywhere. I’ve found plenty of people asking for solutions on how to make diagonal movement accurate, but no one asking if it should be done in the first place.

I use vectors for movement; This makes it easy because you can normalize a vector which eliminates the whole problem of faster diagonal movement.

If you have a max speed, say 6…

if (velocity.getMagnitude() > maxSpeed) {
   velocity.normalize().multiply(maxSpeed);
}

x += Math.sin(Math.toRadians(angleToMove))*wayToMove;
y += Math.cos(Math.toRadians(angleToMove))*wayToMove;

Or quite similar…

Edit: orange451 is mainly doing the same.

orange and Drenius are correct, let me provide some of the theory behind it.

You want to separate movement direction from movement speed.

Direction is a vector, speed is a scalar; specifically the movement of an entity is described by the scalar product of direction and speed.
The direction vector should (needs to) be a unit vector, so that the length of the movement vector (the distance traveled) is equal to speed.
To create a unit vector in the desired direction, you normalize any vector in that direction; the resultant vector will have a length of 1.
How you normalize is dependent on how you are representing your directions and locations, seen in orange and Drenius’s responses.

sin(angle) = adjacent/hypotenuse = vectorWidth/distance;
cos(angle) = opposed/hypotenuse = vectorHeight/distance;

sin(angle) * distance = vectorWidth = distance to move on x axis
cos(angle) * distance = vectorHeight = distance to move on y axis

Wouldnt using vectors to move still result in the odd appearance that the character is moving slower on the diagonals?

I might just not be understanding how vectors work.

Vectors mean that it is moving exactly the same distance, just balanced to both (or more) axes.
So no.

Nope, consider the fact that without normalization, the character appears to be moving faster on the diagonals. It’s because he is.
With normalization, the character moves at the same speed in any direction, and it appears as such. Give it a try!

Little diagram of Euclidean distance, showing the separation of distance into the two dimensional components as Drenius showed, but in reverse (coords to dist, as opposed to dist and angle to coords)

http://www.pro9ramming.com/pictures/formula_coordinate.jpg

Ah, interesting.

I guess I’ll start work on converting my crappy character movement to vectors sooners than I expected. I had full intention on doing so, but for now I just setup a bunch of basic +x +y movements, I was going to use overhaul it with something more practical when I started adding in entities and working with AI/Pathfinding.

But, I guess it’s about time I just go ahead and do it now. :stuck_out_tongue: