Sign in to follow this  
Shamino

About Passing Objects to my Object Adder

Recommended Posts

Shamino    100
So heres my World Class in .CPP Form
#include "World.h"

std::vector<Object*> Scene_Objects;
std::vector<Object*>::iterator Iter;


void World::AddObjectToWorld()
{
	Scene_Objects.push_back(new Object);
}

void World::RemoveObjectFromWorld()
{
	for (Iter = Scene_Objects.begin(); Iter!=Scene_Objects.end();)
{
    if ((*Iter)->MarkedForDeletion)
    {
        delete *Iter;
        Iter = Scene_Objects.erase(Iter);
    }
    else
    {
        ++Iter;
    }
}

};

void World::RemoveAllObjectsFromWorld()
{
	for ( size_t i = 0; i < Scene_Objects.size( ); ++i )
	{ 
		delete Scene_Objects[i];
		Scene_Objects.clear();
	}
};
Just a couple functions to manage my Scene_Objects vector, (which will ultimately be sent to the render for final rendering) Here is my Object Class, its quite simple, but It needs something else, I'm quite sure of it...
#include "MS3D.h"

#ifndef OBJECT_H
#define OBJECT_H

class Object
{
public:

	bool MarkedForDeletion;

	struct Location
	{
		float locx;
		float locy;
		float locz;
	};

};
#endif
And here is the final object (inherits the object class)
#ifndef C_CROSS_H
#define C_CROSS_H


#include "Object.h"

class Cross : public Object
{
public:

	MS3DModel *Model1;

};

#endif
Now, back up there in the um, World class, I have an AddObjectToScene function, that creates a new object, is there any way I can set Cross = to Object, or do I have to switch a few parameters to make this work?

Share this post


Link to post
Share on other sites
Alan Kemp    772
Just make AddObjectToWorld take an object pointer. That way you can also pass any subclass of Object (I suspect you already understand this).


void World::AddObjectToWorld(Object * obj)
{
Scene_Objects.push_back(obj);
}







void World::RemoveAllObjectsFromWorld()
{
for ( size_t i = 0; i < Scene_Objects.size( ); ++i )
{
delete Scene_Objects[i];
Scene_Objects.clear();
}
};





This doesn't do what you think it does. Scene_Objects.clear(); clears the entire vector, the first time through it deletes element[0] then clears the list (so Scene_Objects.size() is 0 the second time through and the loop ends immediatly.) Move it to after the for loop. That is, loop through deleting each element one at a time and then finally clear the whole vector in one go.

Alan

Share this post


Link to post
Share on other sites
Shamino    100
Question though - Do I have to hard code each instance of every object I want to pass this way?

If not, this isn't what I want, I want to dynamically allocate another object of a certain type on command from the user...


EDIT: oops for double post

Share this post


Link to post
Share on other sites
Alan Kemp    772
If I understand you correctly, you want the user to chose a type of object to add to the scene? I would implement that something like this:


enum OBJECTS
{
OBJ_CROSS,
OBJ_CAR,
OBJ_BADGER,
// etc
};

void addObject(int type)
{
Object * obj = NULL;

switch (type)
{
case OBJ_CROSS:
obj = new Cross();
break;
case OBJ_CAR:
obj = new Car();
break;
case OBJ_BADGER:
obj = new Badger();
break;
}

if (obj != NULL)
{
world.AddObjectToWorld(obj);
}
}



Alan

Share this post


Link to post
Share on other sites
Shamino    100
Alan you never cease to amaze me, consise and straight to the answer.

Is this the object oriented way to go? If so, it is perfect.

But it seems to make it so adding new models and objects to my game engine a bit clunky...

I have to add it to the ENUM, I have to add a switch for it, am I just being a little girly coder and complaining? Or is this the way it is? :D

Share this post


Link to post
Share on other sites
Shamino    100
I did find one problem that I can't quite figure out


int World::AddObjectToWorld(int type)
{
Object * Obj = NULL;

switch (type)
{
case OBJ_CROSS:
Obj = new Cross();
break;
}

if (Obj != NULL)
{
World::AddObjectToWorld(Obj);
}
}




When AddObjectToWorld is referenced in my header file, it says it takes an int, and that is fine, up until this part.

World::AddObjectToWorld(Obj);


We get an error like this


--------------------Configuration: NeHeGL - Win32 Debug--------------------
Compiling...
World.cpp
c:\documents and settings\jonathan\desktop\renderengine\world.cpp(20) : error C2664: 'AddObjectToWorld' : cannot convert parameter 1 from 'class Object *' to 'int'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast
Generating Code...
Compiling...
NeHeGL.cpp
Generating Code...
Skipping... (no relevant changes detected)
Renderer.cpp
Error executing cl.exe.
Creating browse info file...

NeHeGL.exe - 1 error(s), 0 warning(s)





I did find this in the MSDN

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/express_76.asp

I think this is what I need to do but I'm not sure how to implement it.

I tried, but failed

int World::AddObjectToWorld(int type)
{
Object * Obj = NULL;
Obj = reinterpret_cast<Object>( type );

switch (type)
{
case OBJ_CROSS:
Obj = new Cross();
break;
}

if (Obj != NULL)
{
World::AddObjectToWorld(Obj);
}
}


Now it just tells me I can't turn Obj into an Object class, and an int into an Obj...

--------------------Configuration: NeHeGL - Win32 Debug--------------------
Compiling...
World.cpp
c:\documents and settings\jonathan\desktop\renderengine\world.cpp(10) : error C2440: 'reinterpret_cast' : cannot convert from 'int' to 'class Object'
Conversion requires a constructor or user-defined-conversion operator, which can't be used by const_cast or reinterpret_cast
c:\documents and settings\jonathan\desktop\renderengine\world.cpp(21) : error C2664: 'AddObjectToWorld' : cannot convert parameter 1 from 'class Object *' to 'int'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast
Error executing cl.exe.
Creating browse info file...

NeHeGL.exe - 2 error(s), 0 warning(s)



[Edited by - Shamino on December 14, 2005 9:04:15 PM]

Share this post


Link to post
Share on other sites
oscinis    209
Notice Alan's example function is addObject(int type), not addObjectToWorld. The function addObject basically wraps to addObjectToWorld, supplying it with the correct object to be added, based off the int type.

Share this post


Link to post
Share on other sites
helix    301
[quote]

int World::AddObjectToWorld(int type)
{
Object * Obj = NULL;
Obj = reinterpret_cast<Object>( type );

switch (type)
{
case OBJ_CROSS:
Obj = new Cross();
break;
}

if (Obj != NULL)
{
World::AddObjectToWorld(Obj);
}
}


[/quote]

You can't cast an int into an object. Basically just eliminate that line all together What you want to do is take the int object id and create the object associated with that id. When you have different types of objects, you can easily add them. So something like the following:


int World::AddObjectToWorld(int type)
{
Object * Obj = NULL;

switch (type)
{
case OBJ_CROSS:
Obj = new Cross();
break;

case OBJ_X:
Obj = new X();
break;

case OBJ_Y:
Obj = new Y();
break;
}

if (Obj != NULL)
{
World::AddObjectToWorld(Obj);
}
}




I would encourage you to look into the class factory design pattern. Because, as you mentioned earlier, this is a little clunky of a way to do it (though by far the easiest).

Share this post


Link to post
Share on other sites
Shamino    100
Fixed it, this should be doing exactly what I want it to



#include "World.h"

std::vector<Object*> Scene_Objects;
std::vector<Object*>::iterator Iter;


void World::AddObjectToWorld(Object * Obj)
{
Scene_Objects.push_back(Obj);
}

int World::AddObject(int type)
{
Object * Obj = NULL;


switch (type)
{
case OBJ_CROSS:
Obj = new Cross();
break;
}

if (Obj != NULL)
{
World::AddObjectToWorld(Obj);
}

return 0;
}



void World::RemoveObjectFromWorld()
{
for (Iter = Scene_Objects.begin(); Iter!=Scene_Objects.end();)
{
if ((*Iter)->MarkedForDeletion)
{
delete *Iter;
Iter = Scene_Objects.erase(Iter);
}
else
{
++Iter;
}
}

};

void World::RemoveAllObjectsFromWorld()
{
for ( size_t i = 0; i < Scene_Objects.size( ); ++i )
{
delete Scene_Objects[i];
}
Scene_Objects.clear();
};

Share this post


Link to post
Share on other sites
helix    301
hmm...that is pretty involved. :) I implemented a class factory that was much simpler. But it was also far less robust and full featured.

What I used was something more like this: Factory Method Pattern

If I were you, start simple with that and then work your way up to the reflective pattern.

Share this post


Link to post
Share on other sites

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