Jump to content
  • Advertisement
Sign in to follow this  
darenking

C++, how can an object know which position it's in in a vector?

This topic is 4865 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This is an interesting one. I have several objects (monsters, let's say) stored in a vector of pointers. When I want the monsters to update their positions, I send each monster a pointer to the vector so that the monster can check its position against each of the other monsters in turn. Of course, I don't want the monster that is being updated to check its position against its own position. It knows the number of each of the other monsters (by this I mean the position where it is stored in the vector, 0 or 1 or 2 if there are three monsters), but it doesn't know the number of itself. For example, it may be the first monster in the vector, monster 0. If it knew that it were monster 0 it could just skip the check if the counter (I mean the counter integer in the for/next loop) equals 0, only checking against monsters that aren't number 0. But how do I tell it that it is monster 0? Should I tell it when I create the monster and put it into the vector? This would cause problems if I were to re-sort the vector at some point, as its position in the vector would change. Or is there a solution involving looking at where it is stored in memory? Hmm. Just thought of an easy solution... when I tell it to update, along with sending it a pointer to the vector I will send it its position in the vector. I've just answered my own post, but I'm going to post it anyway in case anyone wants to tell me that there's totally a better approach!

Share this post


Link to post
Share on other sites
Advertisement
You don't need to know the position of the monster per se. Just do the check if the pointer is not the same as the this pointer.

Share this post


Link to post
Share on other sites
Without commenting on anything else mentioned, you could always check if the monster pointer is pointing to itself.

monsterPointer==this; (C++)



Share this post


Link to post
Share on other sites
Additionally you can use pointer subtraction (with the base) to find an object's index in a memory array.
I think there's even a wrapper for it in STL.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You may be better served in re-examining your class structure. Ask yourself if the objects stored in the vector really need to know about the 'positions' of others. What should be responsible for updating a monster's position? The monster itself or another entity? What if at some point you change how the objects are stored? You would then need to change the logic in all objects that may be stored in the new structure. I think you'd be better off having a controller or manager class which accounts for each object's updating.

Share this post


Link to post
Share on other sites
From a purely object oriented perspective, the monster is doing the moving so the monster should be in charge of updating its own position, given data about the world around it. If its AI calls for it to do something like move towards or away from other monsters, knowing about the other monsters is a necessity.

I would certainly recommend as the most straightforward solution, checking the this pointer against the pointer retrieved from the vector for each monster you look at in the vector.

Share this post


Link to post
Share on other sites
Don't do collision detection at the monster level--do it at the world level, e.g the level above single objects.

As a general rule of thumb, if it's interaction between two or more objects, it should be pushed up a level to a class that already knows about the objects. So, in this example, it might look something like this:

class Monster {
Rect rect;
public:
const Rect& getRect() {
return rect;
}
};

class World {
Actor monsters[NUM_MONSTERS];
public:
void check_collisions() {
for(...) {
for(...) {
if(colliding(monster1.getRect(), monster2.getRect())) {
blah
}
}
}
}
};

I usually prefer pro-active collision prevention, which involves telling the world to move a given object and literally preventing it from going through other objects, but that's for another discussion.

[Edited by - bytecoder on July 21, 2005 6:40:14 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by TDragon
From a purely object oriented perspective, the monster is doing the moving so the monster should be in charge of updating its own position, given data about the world around it.


I disagree, that introduces dependancies (the outside world) which may and will change. You also limit yourself to a single implementation of the outside world, so you will not be able to reuse your monster class as easily - if one project is using a simple terrain mesh to which the monster is bound to, it will not be reusable in a project which uses a much more physics based engine where obstacles are represented by objects rather than gaps in the terrain mesh.

From an architectural perspective, what I am doing is arguing that the monster is being moved by the mechanics of the game world, and thus the game world should be in charge of updating the monster's position, not the monster itself.

Quote:
If its AI calls for it to do something like move towards or away from other monsters, knowing about the other monsters is a necessity.


If the AI controling the monster, which can be concieved as a completely seperate entity (which easily allows for multiple types of AI to be used - a cowardly AI, a brave AI, a very stupid AI, a boss's AI) needs this information.

All this said and done:

If you are storing your monsters in a container by pointer like so: std::vector< monster * > foo;

You can get an iterator to said object like so (assuming we have a pointer, in this example we use "this" as if in a member function of monster):

std::vector< monster * >::iterator this_iterator = std::find( foo.begin() , foo.end() , this );
if ( this_iterator == foo.end() ) {
//"this" isn't in foo
}
//if we really want the index rather than an iterator:
size_t this_index = std::distance( foo.begin() , this_iterator );


If the monster is held by value, assuming you have an appropriate operator== defined (e.g. return this == &other;) you may do:

std::vector< monster >::iterator this_iterator = std::find( foo.begin() , foo.end() , *this );
if ( this_iterator == foo.end() ) {
//this isn't in foo
}
size_t this_index = std::distance( foo.begin() , this_iterator );

Share this post


Link to post
Share on other sites
also if you have a member function for each class to do the movement operations of instantiated objects you need one function call per object which is unnecessary expensive

and in most cases where you get complexe movement function you can t even inline them due to their size

and back to topic


if you know the startaddress of the vector and the objects address you can do this with a pointer subtraction and the "%" operator

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!