Simple 2D game question

Started by
5 comments, last by chiranjivi 14 years, 1 month ago
I'm trying to figure out how to make an actor in a 2D tiled game take a direct-looking path to a target, but I can't seem to figure it out. To explain... Right now, the movement code is basic as can be and looks like this:

void Actor::walk()
{
	if ( dest_y < actor_y ) { --actor_y; }
	if ( dest_y > actor_y ) { ++actor_y; }
	if ( dest_x < actor_x ) { --actor_x; }
	if ( dest_x > actor_x ) { ++actor_x; }
}

Which produces a movement pattern like this ('A' is the actor, 'D' is its destination): current Now what I'd prefer is for the actor to take a more natural-looking path, where it walks the same number of tiles, but doesn't go diagonally and then straight. Like this: desired However I'm clueless as to how to make the actor do that. v[headshake]v Suggestions?
Advertisement
Try incrementing the x value of your character two times in stead of just incrementing it once. That way he moves 2 on x and only 1 on y.
Two suggestions:

1. Use a pathfinding algorithm like A* or Djikstra. Pros: accuracy, obstacle avoidance. Cons: more expensive cpu-wise, more complex to implement, although you can look for libraries that already have this implemented.

2. Use trigonometry. Use a reference line, like the horizontal axis. Then calculate the angle between the reference line and the line formed thru points A and D. Then you will have some movement magnitude, let's call it m.

Then,

x += m * cos ( angle ) and y += m * sin ( angle ). This will move the actor in a straight, crow's flight line, but does not account for obstacles, yet it is simpler than something like A*.
Since you have a grid system, why not calculate the slope? You could use the equation y=mx+b. Then when you increment X by 1 it will calculate the new Y.
I would recommend learning about 2D vector maths to solve this kind of thing.

It can look a bit intimidating at first but it is actually pretty simple and I would say one of the most essential tools in a 2D game developers mental toolkit.

Once you've got your head round it, you will never look back.
Here you go. This lets you figure out the movement one step at a time as long as you can re-check the distance to the target, and store the 'accumulator' (as part of the actor data, perhaps).
Thanks all for your thoughts about this. Having read Zahlman's post, and figured out the vector math bits, I decided to go with the idea of storing an 'accumulator' of movement as part of each actor's data.

So, I assigned each actor a floating-point X and Y co-ordinate as well as integer X and Y co-ordinates, and each time a move is made, I would take the vertical and horizontal components of the motion, add them to the floats, and make the integer co-ordinates equal to the floats rounded to the nearest integer.

This works, pretty much, except for one issue, which is that even if a actor is moving towards something which is (for example) a long way to the right, and only a few squares above... every now and then the floating-point addition will add, say, +0.9 to X, and +0.1 to Y, and the Y-increment will trigger an upward move but the X-increment won't trigger a sideways move.

What happens in this case is that the actor will make a move straight up, even when the target is almost directly to its right, which kind of makes the pathing look weird:

im on a boat

The "!" represents the undesirable move here, obviously. It happens more frequently the closer to diagonal the straight-line path is. I'd like to stop this from happening as, again, it appears to be an unnatural path for the actor to take, but I'm not sure how to modify my implementation to effect that.

This topic is closed to new replies.

Advertisement