🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Forward =)

posted in A Keyboard and the Truth for project 96 Mill
Published August 30, 2005
Advertisement
I find it funny that I thought there would be a time (notably after the finish of Morning's Wrath) that I would stop working on games, I have found that this simply won't be the case.

Not more than a week of being done with the development of MW, and already my mind is ticking once again =D

Of course there are things to be done with MW and that will come first, but I have had a little more time lately, AND I dont have that voice saying (finnish this game first!), so at the moment my thoughts are dwelling upon the next iteration of our game engine.

On sunday I did a bit of work on a prototype, it was for an 'object' class, and I implemented a system that I designed, I would have liked to use it in MW, but we know what happens to programmers that rip the engine apart at 3/4 development completion =)

The outcome of the protoype is an Object class and two MACROS,

DeclareObject(classname,superclass)
ImplementObject(classname)

these are used for subclassing object (which will be done a lot).

So what does 'Object' do you ask?

1. Robust type information

Object::getInstanceType() - returns a Type object of the objects true instance type.

Type t = obj->getInstanceType();

Object::getClassType - (static) returns a Type object of the class type.

Type t = SomeType::getClassType();

Object::instanceOf - hierarchy aware inheritence test

bool b = obj->instanceOf(obj2->getInstanceType());

Type::getName() - returns the string name of a type

std::string str = t->getName();

Type::getID() - returns the numerical ID of a type

unsigned long id = t->getID();

Type::forName(std::string name) - returns a type for a given string name.

Type t=Type::forName("SomeType");

Type::newInstance() - creates a new instance of the type

Object* obj= t->newInstance();



These features were priceless in the creation of Morning's Wrath, and unfortunetly had to be fullfilled in rather non-elegant ways. But now, I have a well developed solution!




2. Smart Pointers

To reduce the amount of pointer errors and to promote efficant use of memory I have constructed a Pointer object, which can be used as a real pointer, and supports reference counting.

It can be used a lot like a C# or Java pointer(object), in that it handles instantiation and copying and destruction properly, it will make programming in C++ somewhat easier I imagine.

The Source:

Pointer.h
#if !defined(POINTER_H)#define POINTER_Htemplate <class T> class Pointer{public:	Pointer()					{counter=0;}	Pointer(T* ptr)				{counter=0; acquire(new Counter(ptr));}	Pointer(const Pointer& p)	{counter=0; acquire(p.counter);}	T& operator*()				{return *counter->ptr;}	T* operator->(void)			{return counter->ptr;}	T& operator[](unsigned i)	{return counter->ptr;}	~Pointer(void)				{release();}	Pointer& operator=(T* ptr)    {        if(this->counter&&this->counter->ptr==ptr)		{			return *this;		}        acquire(new Counter(ptr));        return *this;    }	Pointer& operator=(const Pointer& p)    {        if(this != &p)		{            acquire(p.counter);        }        return *this;    }private:	struct Counter{		Counter(T* p = 0){ptr=p;count=0;}		T* ptr;		unsigned long count;	}* counter;	void acquire(Counter* c)    {		release();        counter = c;        if(c)++c->count;    }    void release()    {		if(counter)		{            if(--counter->count==0)			{                delete counter->ptr;                delete counter;            }			counter = 0;        }    }};#endif


Examples of usage:
Pointer ptr;//assignment from raw pointer(will release existing if applicable)ptr=new std::string("omg cool!");//increased referencePointer ptr2=ptr;//indirectionstd::string str=*ptr2;//dereferencingconst char* cptr=ptr2->data();//Array UsagePointer<int> intArray(new int[100]);int i=intArray[20];


In short, it's fricken awesome =D


3. WTF? Why must you roll your own?

a. To learn and become a better programmer
b. It was not all that hard to build
c. Self written components cater directly and only to your needs
d. Rolling my own components hasn't caused me much harm yet (points to completed game) ;)

yay!
Previous Entry HTML Template
0 likes 3 comments

Comments

ildave1
It is always a pleasure to view code written by well extablished individuals, to see their ideas and methodologies for adapting to the environment at hand.

Keep up the motivating work!
August 30, 2005 08:05 PM
Seriema
You and your darned reinvent the wheel syndrome! =P Use your time for NEW features instead! *rants* hehe

What's up with with the RTTI? What do you use it for? *curious*

hehe ;)
September 01, 2005 03:53 PM
EDI
RTTI is a key part of serialization, and complex programming as a whole.

Serialization:

lets say i want to save an object and load it again later.

it is very important to save a description of exactly what type of instance the object was.

when you reload it, you need to look at the kind of instance it was and then be able to recreate it, without RTTI this is somtimes nearly impossible, or at least very hard.


example:

//Character extends Object
//Save
Character* ch=new Character();

ch->saveType();
ch->saveData();

//Load
Type t=loadType();
ch=(Character*)t->newInstance();
ch->loadData();


this way, an object can be remade perfectly without needing compile time knowledge of what type it was.


Other Stuff:

while most programing problems can be solved without RTTI, somtimes they are easier solved with it:


example:

for instance, say you had three types of item Potion,Spell and Weapon, and all inherited from Item.

when a character takes an item it is dumped into an array, which only assures type knowledge from Item and up.

if you need to know how many potions you have, you can itterate the list and use RTTI to determine if an Item is in fact a Poition, using instanceOf.

"But Raymond!" you say, "why not store potions,weapons and spells in thier own arrays!?", doing so would solve that problem, _however_ it can complicate other such things;

for instance, if you ever need to see if you are carrying a certain item you will have to itterate over three lists.

it also means that you cannot simply extend Item at will and allow Character to use it, a new array and a new set of accessors would need to be added, AND, this new array would have to be factored into all of the existing 'multi-array-checking' code, clearly a pain =)

There are of course even more solutions that can solve what i just proposed, but IMHO, the best solutions are the ones that dont cause the need for more solutions =) As long as RTTI isn't blatently abused it is perfectly fine, and useful.

and just so you know, the functionality of my RTTI was modeled after the JAVA functionality, since I found it to be a dream to work with =)



September 02, 2005 01:02 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement