Storing my game objects

Started by
13 comments, last by Motorherp 19 years, 6 months ago
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

If it isn't working, take a bath, have a think and try again...

Advertisement
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.
[size="1"] [size="4"]:: SHMUP-DEV ::
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

If it isn't working, take a bath, have a think and try again...

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

If it isn't working, take a bath, have a think and try again...

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.
[size="1"] [size="4"]:: SHMUP-DEV ::
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

If it isn't working, take a bath, have a think and try again...

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

If it isn't working, take a bath, have a think and try again...

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.
enum Bool { True, False, FileNotFound };
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.
[size="1"] [size="4"]:: SHMUP-DEV ::
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

If it isn't working, take a bath, have a think and try again...

This topic is closed to new replies.

Advertisement