Page 1 of 1

Problem with lists.

Posted: Wed Apr 19, 2006 4:25 pm
by magicat
Okay so I've been working on an "Entity Management" system for my game. Basicly any object in the game(buildings, vehicles, etc) will be an entity, so I'm using a class with a list to manage all the entities. I'm able to create my EntityManager class, and add a couple entities to it fine. Each entity just loads a simple model and contains an Update() function that is called every game loop. Right now the update function just moves the entity a bit up. I have an Update() function in my EntityManager object as well, that loops through all the Entities stored in it and calls their update methods. The problem is, the loop seems to loop through the entities and call the update method on just one of the entities multiple times, resulting in the entity moving faster than it should normaly, and all the other entities just sit there since they're not being updated. I think this might be a problem with my use of the iterator for the list, but I'm not sure. This is my first time using lists in c++ so I'm still getting the hang of it. I create a list of GameEntity object pointers like so in my EntityManager.h file:

Code: Select all

        std::list<GameEntity*> entityList;
        std::list<GameEntity*>::iterator iEntity;
Then I add entities to the list with the AddEntity function in EntityManager.cpp:

Code: Select all

void EntityManager::AddEntity(GameManager* tGame, GameEntity* tEntity)
{
    tEntity = GameEntity::Instance();
    tEntity->Init(tGame, false, false);
    entityList.push_back(tEntity);
}
And here is my Update function in EntityManager.cpp:

Code: Select all

void EntityManager::Update(GameManager* tGame)
{
    for(iEntity = entityList.begin(); iEntity != entityList.end(); iEntity++)
    {
        GameEntity* tEntity = *iEntity;
        tEntity->Update(tGame);
    }
}
Its almost like the loop works correctly, but tEntity always points to the same GameEntity. Any ideas of what I'm doing wrong?

Posted: Wed Apr 19, 2006 4:31 pm
by sudi
Iguess u can't just increment the pointer...i could be wrong and there is another error.
But actually would use a vector.

std::vector<GameEntity*> entityVector;

and now only the Update code changes:

void EntityManager::Update(GameManager* tGame)
{
for(int i=0; i < entityVector.size(); i++)
{
entityVector->Update(tGame);
}
}

Posted: Wed Apr 19, 2006 4:43 pm
by CuteAlien
In AddEntitity you ignore the entity parameter, as i in the first line you'll just get a new pointer to that GameEntity::Instance();

Posted: Wed Apr 19, 2006 4:45 pm
by sudi
U don't know whats iside his Instance method.......

Posted: Wed Apr 19, 2006 4:50 pm
by CuteAlien
Sudi wrote:U don't know whats iside his Instance method.......
No i don't, but guessing from the calling convention classname::Instance i guess it might be a static function. Maybe he sets it to return the pointer which he uses as parameter before calling this function, but that doesn't make much sense.

Posted: Wed Apr 19, 2006 5:22 pm
by magicat
Okay so I think somethings definitely wrong with the method I use to create new GameEntity objects. I converted from lists to vectors(which do you think is better suited for this task by the way?) and got the same result. I add objects this way, with the GameEntity::Instance() because its the way I learned to do it for my game state system, which with that I realize theres always only one instance of each game object, so that may be why that method doesn't work here. I'm not exactly sure how to create objects the old fashioned way in C++(still new to it as you've seen), but I'll look it up and try it that way and see if it works. Oh and here is what the Instance() method does:

Code: Select all

GameEntity GameEntity::tGameEntity;

//! Return an instance of this class
GameEntity* GameEntity::Instance()
{
    return (&tGameEntity);
}
Update: I tried the "traditional" way of making objects, or at least what I think it is. Which turned out to be the same, just not setting it to the Instance()? It just ended in the crashing of my program. Now I'm more confused. The strange thing is that when I use AddEntity, it calls the Init() methods correctly of the objects - since Init() is responsible for adding the mesh, and both show correctly. If its able to do this, wouldn't mean my problem is with the vector/list and not the object creation?

Posted: Wed Apr 19, 2006 7:04 pm
by sudi
Try the following:

std::vector<GameEntity> entityVector;

to add a entity do this:
entityVector.push_back(GameEntity);
entityVector[entityVector-size()-1]->Init(tGame, false, false);

//and updating is still
void EntityManager::Update(GameManager* tGame)
{
for(int i=0; i < entityVector.size(); i++)
{
entityVector->Update(tGame);
}
}

What i don't get is u r passing the tGame instance on init to the entity and than on every update.......why don't just pass a pointer in the init function and save it in the entity than u wouldn't have to pass it on every update.

Posted: Wed Apr 19, 2006 8:34 pm
by magicat
Okay I changed it over to use the actual object, and not pointers to it. Works :). For now at least. And thanks for the pointer on passing the tGame pointers(pun intended). I had been wondering if I actualy needed to do that or not. Some code I learned off of for my game state management passed the pointers in every method, so I've been doing that for my entity stuff too, as habit. I took it all out now, much simpler, thanks for the advice :).

Posted: Wed Apr 19, 2006 9:12 pm
by sudi
But u have to pass the game pointer on the entity creation!!
otherwise the entity will have the old gamestate when it was created!
pass it with

&tGame

Posted: Wed Apr 19, 2006 10:35 pm
by CuteAlien
Your Instance() function does not create an object. It just returns a pointer to an Object which has already been created.

If i get it right, what you try to do is dynamically creating objects. You do that by creating them on the heap with new.

Code: Select all

GameEntity * entity = new GameEntity();
Now you can pass the variable 'entity' to your add function. No need for the Instance call there. Just remember that each memory allocated by 'new' must be freed at the end with 'delete' otherwise you will have memory leaks.

The reason it crashed formerly was probably because your objects where created on the stack memory. Pointers to such objects are only valid as long as the stack object exists (usually within the scope defined by { } ). Your object referenced by Instance() was defined globally so the pointer is valid all the time - but you would have to create another variable for each object (or if done your way even another class for each object - this is typical singleton code where you only have one object for a class).

Using objects instead of pointers is also ok. But learn to use pointers anyway - you will need them when working with c++. And copying objects is in most cases way slower than using pointers (depends on the size of the object).

Posted: Thu Apr 20, 2006 12:26 am
by magicat
That explains a lot CuteAlien, thanks. I was able to change it back to storing object pointers and it appears to work correctly :).