简体   繁体   中英

How to get the list of object within a distance from a given position in C++

  • I have a collection of object with a position (x, y)
  • These objects randomly move
  • Could have thousands of it

At any moment I would have the list of object in a (constant) radius RAD from a position POS.

Edit - Context : It's for a gameserver, which would (utopically) have thousands of players. When a player moves/[makes an action], I want to send the update to others players in the radius.

The easy way, every time I need the list :

near_objects;
foreach( objects o ) {
    if( o.distance( POS ) < RAD )
        near_objects.add( o )
}

I guess there are better/faster methods, but I don't know what to search.

Here are two suggestions.

Usually you compute distance using sqrt( (ax-bx)^2 + (ay-by)^2 ) and the expensive part is computing sqrt(), if you compute RAD^2 once outside the loop and compare it to the inside of the sqrt() you can avoid computing sqrt() in the loop.

If most of the objects are far away, you can eliminate them by using

if( abs(a.x-b.x) > RAD ) continue;
if( abs(a.y-b.y) > RAD ) continue;

I assume this is for some kind of MMO - can't imagine 'thousands' of players in any other scenario. So your problem is actually more complex - you need to determine which players should receive the update about each player, so it turns into O(n^2) problem and we're dealing with millions. First thing to consider is do you really want to send updates based only on distance? You could divide your world into zones and keep separate lists of players for each zone and check it only for these lists, so for m zones we have O(m * (n/m)^2) = O(n^2/m). Obviously you also want to send updates to players in the same party and allow players near zone transition spots to know about each other(but make sure to keep that area small and unattractive for players so they don't just stand there). Also considering huge world and relatively slow player speed you don't have to update that info all that often. Also keep in mind that memory/cache usage is extremely important for performance and I was referring to list as an abstract term - you should keep data accessed in tight loops in arrays, but make sure elements aren't too big. In this case consider making a simple class containing basic player data for those intensive loops and keep a pointer to a bigger class containing other data.

And on a total side note - your question seems to be quite basic, yet you are trying to build an MMO, which is not only technically complicated, but also requires a ton of work. I believe, that pursuing a smaller, less ambitious project, that you will be actually able to complete would be more beneficial.

You could put your objects into an ordered data structure, indexed by their distance from POS. This is similar to a priority queue, but you don't want to push/pop items all the time.

You'd have to update an object's key whenever it moves to the new position. To iterate over the items within a given radius RAD, you'd simply iterate over the items of this ordered data structure as long as the distance (the key) is less than RAD.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM