Steering behaviours and wrap-around worlds

Recommended Posts

I have a wrap around world (only in X direction) and I intend to use steering behviours to control AI units so that they seek and arrive at the player. Now this in theory works fine except when the player crosses the wrap-around barrier. For example if the player is in a world that is 0 - 100 and crosses the 0 barrier the AI units immediately switch direction because the player is now at somewhere near 100. This would be fine if the camera were static and the whole world was in the view frustum but in my case the camera chases the player so you get AI units that suddently veer away from the player for no apparent reason (the wrap-around points are not obvious to the player). I have thought of two of solutions to this, both of which introduce complexity: 1, Keep track of what the AI unit is chasing and if the distance suddenly increases by a huge amount (target crossed the barrier for example) then compensate for the barrier crossing. 2, Transform the AI and the target into a common screen space rather than world space whenever seeking and arriving is in operation. They will be in relation to each other at all points then. Anybody have any other ideas?

Share on other sites
Palidine    1315
you just need a simple function to determine the shortest direction on the x-axis to the player. In a wraparound world the longest distance 2 things can be away from eachother is lengthOfAxis/2. So, in your world, if the difference in x coords is greater than 50, go "away" from the player along the x-axis.

-me

Share on other sites
rileyriley    235
Once your world wraps around, you no longer have a unique system of coordinates. (50, 50) is the same as (50, 150) and (50, -50), if you see what I mean. I think I might try the tack of considering several of the many coordinates of my target in the tracking AI, and going after whichever is the closest point. I'm sure you could do it and only need to consider two or three possible coordinates.

This is the same as your #2 and the solution posted immediately above this post, but it maintains a kind of mathematical consistency that I like.

Example along one axis: AI is at 90 and target is at 99. This is the same as AI at -10 and target at -1. Anwyway, when the target moves up to 105 (5 after wrapping), now the AI is at 90 and the target is at 5 (or 105). 105 is closer... go for that! After all, 105 and 5 are equivalent. This is your #2 exactly, with an extremely convenient common coordinate space.

Share on other sites
Timkin    864
The easiest solution is actually just to add a third dimension to your coordinate system, being the "screen number". If a unit (player or AI) wraps around from right side to left side, increment the screen number coordinate. If they wrap around from left to right, decrement that coordinate. Then your steering behaviours can easily be solved in these 3 dimensions, since you can work out an equivalent 2D coordinate by adding "screen_width * screen_number" to the x-coordinate in the 3D system and compute your steering function in 2D.

Cheers,

Timkin

Share on other sites
NQ    328
Yeah, well, there's many ways to do this.

The previously suggested solutions are simple and do function, but I would like to make an addition. I find my way to be very similar in many ways, but even simpler.

Perform all pathfinding calculations in an artificial coordinate system; not the real one. In this coordinate system, the agents position is coordinate 0:0. Every other coordinate - such as the players - is mapped into this system, relative the agent. Everything is relative the agent.
The edges of this coordinate system is the opposite side of the world. When you have all coordinates inside this new space, you'll have a very easy time calculating whatever you want. Such as the shortest path, or the direction to wherever.

This is the way I would personally do it. It's easily implemented, without any fancy mathematics, and it does not hinder you from adding additional functionality later. A simple, functioning and expandable solution, right from the start.
Good luck!

Share on other sites
Nice - I like that idea.

Share on other sites
Timkin    864
Quote:
 Original post by NQThis is the way I would personally do it. It's easily implemented, without any fancy mathematics, and it does not hinder you from adding additional functionality later. A simple, functioning and expandable solution, right from the start.Good luck!

...with the added computational expense of requiring multiple coordinate transforms every frame. As for "without any fancy mathematics", you're actually suggesting the OP increase the mathematical complexity of each frame by requiring said transforms. None of the aforementioned suggestions requires any complicated mathematics, so suggesting otherwise to sell your solution as the best one is inappropriate. Might I suggest that next time, offer your proposed solution without bias and allow the OP to decide what he or she prefers.

Cheers,

Timkin

Share on other sites
The solution proposed is similar to #2 that I had originaly proposed.

In some ways TimKin I am already handling it your way since the world I am performing this in is already segmented horizontaly into segments.

They jury is still out on which method I am going to use and I may try out all of the suggestions here. I am not too concerned with the amount of processing requirements as this really isn't going to be the bottleneck. But I live by the mantra 'the simplest way'

Share on other sites
NQ    328
... I had a reply here, but I noticed there's something wrong with my math, so I removed it until I've figured it out...

[edit:]

At the time I really did believe my way was much simpler, but you're right - I shouldn't say so anyway.

I figured out what my math error was now. Turns out I was underestimating how many lines of code was necessary to translate the coordinates... =) You need 2 rows (including 2 if-statements), but I thought you needed a whole lot less.

I don't like to discover that I miscalculated, so I've sort of obsessed over this riddle for the last 45 minutes... heheh... I find it funny now as I go back over the thread, and see OP start the thread with a good solution (#2) and then Palidine, rileyriley and myself all reinvent 3 mutated clones of the same solution.
Actually, Timkin is the only one who posts a different solution, and funnily - that's the one solution which doesn't work... :D

[Edited by - NQ on April 26, 2006 8:34:18 AM]

Share on other sites
Timkin    864
Quote:
 Original post by NQActually, Timkin is the only one who posts a different solution, and funnily - that's the one solution which doesn't work... :D

You're quite sure about that, are you? The solution I proposed works just fine.

What you're neglecting is that the OP didn't actually specify the problem very clearly, so that in fact there are at least two behaviours (that I can currently think of) that satisfy his requirements. One is to continue to follow the target through the wrap-around edge (my suggestion) and the other is to find the shortest distance to the target at every iteration, irrespective of the cylindrical coordinates of the world (the other suggestions). It should be obvious why the former is more simple than the latter and requires far less computation.

Perhaps before criticising other people, you might give more thought to what they're saying. While I admit I'm not perfect and I do make mistakes, they are rare... and I don't typically open my mouth to sprout bullshit.

Share on other sites
NQ    328
Hey man, take it easy...
I withdraw my previous statement "which doesn't work", and replace it with the more accurate version "which solves a problem which likely is different from what the OP was talking about".
I didn't write the long version, because it didn't explain the humour I saw in it.

Let's forget about that and get back on-topic...

XiotexStudios, if you're still looking for a solution, then this might help:

halfworld = worldsize / 2; targetX = player.x; if (targetX < (agent.x - halfworld))	targetX += worldsize;if (targetX > (agent.x + halfworld))	targetX -= worldsize;targetX -= agent.x;targetY = player.y - agent.y; Move_In_Direction(Get_Direction_To(targetX, targetY));

The 2 if-statements, plus the following 2 lines, is what converts the players coordinate to agent-space. The Get_Dir_To()-function calculates a direction from coordinate 0:0 towards the supplied parameter.
You are probably already using such a function, and only need to modify it to assume that the from-coordinate is always at 0:0.

Good luck!

Share on other sites
Thanks - I'll give it a go..

Share on other sites
Timkin    864
Quote:
 Original post by NQI withdraw my previous statement "which doesn't work", and replace it with the more accurate version "which solves a problem which likely is different from what the OP was talking about".

*sigh*.

If you have evidence as to any error in what I wrote, then please post it. If not, then your opinions are based only on supposition and misunderstanding and are therefore inappropriate and inflammatory. Please do not treat other forums users in this manner.

Timkin