Sign in to follow this  

Storing my game objects

This topic is 4823 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

Hi, This possibly should go in general programming but as I will be using this for my D3D stuff I thought I'd ask you guys in here. I'm wanting to store any type of object within a dynamic array, now coming from a MFC background I could use CMap, CObList, CPtrList, CObArray, CMapStringToOb etc, etc...But as I'm not using MFC in my game code, I was wondering which object in the STL library is good for what I'm asking. I know there is the vector class, can this be used to store any type of object ? Best regards, Steve

Share this post


Link to post
Share on other sites
An std::vector would meet the dynamic array requirments but as far as I know it can only store objects of the same type (or at least of the same size with casting). One way of overcoming this would be to union all your different objects types together into a 'mother' object with flags used to specify object type. However this does mean that each space in the vector will take on the size of the biggest object in the union and so there is the potential to waste a lot of memory. If you don't mind having objects in different places in memory but just want to be able to access them all from the same array then you can create an object handle struct which basically just contains a union of pointers to all the object types plus a flag. This would waste less space but would put a extra de-referance in your path. I doubt this is the only way to do it and maybe not even the best but its the first that came to mind.

PS: I'm not totally sure how well std vectors and vector members with pointers in them combine either. If there's any problems with this if someone could shed some light on the situation.

Share this post


Link to post
Share on other sites
Thanks Motorherp,

I was thinking along the lines of :

class CShape
{
// methods, members etc..
};

class CCube : public CShape
{
// methods, members etc..
};

class CObjectManager
{
public:
vector<CShape> m_shapes;

};

Now, when I create say two cubes :

CCube* pCube = new CCube;
CCube* pCube2 = new CCube;

CObjectManager::GetInstance()->m_shapes.push_back(*pCube);
CObjectManager::GetInstance()->m_shapes.push_back(*pCube2);

Would this not work due to the polymorphic behaviour of objects being derived from CShape and thus all being CShape objects ?

In mfc this would be very simple :

CObArray m_shapes;

m_shapes.Add( (CObject*) new CCube() );
m_shapes.Add( (CObject*) new CPyramid() );

for( int i = 0; i < m_shapes.GetSize(); i++ )
{
CShape* pShape = (CShape*) m_shapes.GetAt( i );
// do whatever pShape->Render()
}

Surely the same can be done with STL or do I have to go and write my own dynamic Template array ?

Kind regards,
Steve

Share this post


Link to post
Share on other sites
Hi,

This seems to do the trick :


vector<CShape> shapes;
CShape* pShape = new CShape;
pShape->m_Xpos = 10;
shapes.push_back( *pShape );

CShape* pShape2 = new CShape;
pShape2->m_Xpos = 20;
shapes.push_back( *pShape2 );
pShape2->m_Xpos = 20;

for( vector<CShape>::const_iterator viter_ = shapes.begin(); viter_ != shapes.end(); ++viter_ )
{
CShape* pSh = (CShape*) viter_;
}





Best regards,
Steve

Share this post


Link to post
Share on other sites
I'm afraid not, what you decribe is polymorphism going in the wrong direction. Although instances of inherited classes can be treated as their base class, base class instances cant be treated as types which are inhereted from them. Also with stl vectors, when you push back it will allocate an amount of space to fit the type which it thinks it holds (in this case CShape since thats what you passed to the vector during initialisation). Even if you found a way to pass CCube in, any data after the CShape data would be lost.

Is it strictly necessary to be able to access all your different data types from the same array. Why not create a manager class which handles a dynamic array for each shape type. So for example when you call the managers CreateCube function it allocates a space for a new CCube in the CCube vector and passes out a reference to it so the user can fill the data in. This way you always know what type you are handling without flags. Plus, because of the way the data is arranged in contiguos memory in lists of type, you'll get a great performance boost because you are maximising cache hits and code coherence when processing this data.

Share this post


Link to post
Share on other sites
Thanks Motorherp,

I can't believe this is not possible using STL in the same way as this is easily done in MFC. All I want is a class that holds all the objects in my game. Does STL not support RTTI ?
What you describe as having different vectors for each type of object sounds a great idea, I just took it that you could store any type of object within the same vector much the same as you can in a lot of the mfc container objects. Having said that, you have to cast always to CObject in mfc or derive your class from CObject.

I really appreciate your advice Motorherp, many thanks!

Steve

Share this post


Link to post
Share on other sites
Ok, I have come up with this with what you have told me Motorherp :


class CObjectManager
{
vector<CCube> Cube;
vector<CPyramid> Pyramid;

public:
void CreateCube();
void CreatePyramid();

void RenderObjects();
};


void CObjectManager::RenderObjects()
{
for( vector<CCube>::const_iterator viter_ = Cube.begin(); viter_ != Cube.end(); ++viter_ )
{
CCube* pCube = (CCube*) viter_;
if( pCube )
{
pCube->Render();
}
}

for( vector<CPyramid> viter_ = Pyramid.begin(); viter_ != Pyramid.end(); ++viter_ )
{
CPyramid* pPyramid = (CPyramid*) viter_;
if( pPyramid )
{
pPyramid->Render();
}
}

}

void CObjectManager::CreateCube()
{
// create vertices etc for cube
CCube* pCube = new CCube;
pCube->Initialise();
Cube.push_back( *pCube );
}

void CObjectManager::CreatePyramid()
{
// create vertices etc for cube
CPyramid* pPyramid = new Pyramid;
pPyramid->Initialise();
Pyramid.push_back( *pPyramid );

}





This is something I've just quickly thrown together, is this looking correct ?

Best regards,
Steve

Share this post


Link to post
Share on other sites
If you are using interfaces (such as CShape) then you should probably be storing pointers, rather than instances.

You need to prefix all STL names with std::. (Unless you add "using namespace std;" after all your includes, but that's a bad practice.)


class MyClass {
std::vector< CShape * > myShapes_;
};


In general, you should make sure you separate value types (Vector3, Plane, possibly String) from object types (anything with polymorphic behavior is an object), and store (generally) copies of values, but pointers to objects.

Share this post


Link to post
Share on other sites
I'm not all that hot on MFC or STL for that matter so I can't say for sure there isn't a nice way of replicating these MFC functionalities. I'm not really sure that level of abstraction is really needed or desirable though. When designing these sorts of things I usually work of the principle that the more information you can assume, the less checks and calculations you need at run time, and hence the more efficient your system. It can be nice to build a wrapper around the core system once its finished though so the user can interface with it as easily as possible. Since this interface type stuff doesn't get called that often at run time you can abstract it as much as you want to make it as simple to use as possible.

Good luck with your engine, sounds interesting. Any more questions just let me know.

Share this post


Link to post
Share on other sites
Thanks again Motorherp, I'm sure I will have more questions in the future ;-)

hplus0603 - thanks for the advice, I've only been using STL for the last 30 minutes so was using the namespace directive, will change to use the std::

As for storing pointers, am I not storing pointers to the Cube and Pyramid objects in the vectors ? I guess I should use :

std::vector<CCube*> Cube;
std::vector<CPyramid*> Pyramid

Kind regards,
Steve

Share this post


Link to post
Share on other sites
Bah, two posts in a row, I can't keep up with you :). Thats the sort if thing I'm talking about. Now when you process all your objects in turn you'll be stepping through memory linearly which is much faster than jumping around. With your create functions you might want something like this though:


inline CCube& CObjectManager::CreateCube()
{
// create vertices etc for cube
Cube.push_back( CCube() );
return Cube.back();
}





Now when the user wishes to create a new cube they'll get a reference back to the new cube so they can fill out its properties with whatever they want.

PS: Are you sure storing pointers is the best thing hplus0603?? By storing an array of instances you get better cache performace when processing them.

Share this post


Link to post
Share on other sites
Thanks again Motorherp,

I'm actually in work, I've come into the office for a bit of peace and quiet (I've a young baby at home which makes it difficult to concentrate sometimes!). The createcube method would be part of my CCube class which would basically fill in the vertices and index buffer needed in order for it to be rendered. The CCube class also has a method for setting its world position. I guess I could return the object, wouldn't do any harm ;-)

Many thanks,
Steve

Share this post


Link to post
Share on other sites
No problem. Maybe you can answer a question for me. Like I said I'm not that hot on STL and the above code snippets have just made me think about the correct usage of vectors. Do you know which is correct out of these two:


CCube* pCube = new CCube;
Cube.push_back( *pCube );


or


Cube.push_back( CCube() );


I've got a feeling that vectors copy the information passed in so the top way will cause a memory leak since its effectively creating two instances. But maybe thats correct and the bottom way is wrong in which case does the information in the vector dissapear as soon as you leave the current scope?? And what effect if any does calling reserve have on this problem?? Any ideas??

Share this post


Link to post
Share on other sites
Hi Motorherp,

Well, I'm not too hot on STL, only been doing it just over an hour now ?!

I have a feeling that the top way does work, I've just debugged using this and it is fine. Of course, you would have to do a for loop and delete these objects from the vector when finished with them i.e.when the game ends.

So, it does retain the information using the top way.

Share this post


Link to post
Share on other sites

This topic is 4823 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this