Entity Attributes

Post your questions, suggestions and experiences regarding game design, integration of external libraries here. For irrEdit, irrXML and irrKlang, see the
ambiera forums
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Entity Attributes

Post by sudi »

I have been working on my gameengine for ages now and it is preatty useable already and i made some games with it.(i guess all of them arepostet on this forum) anyway. One thing i came across while programming the games is the communication of entities and exchange of variables. I did this with passing void* pointers in clback functions and implementing a simple get/setVarINT/FLOAT and so on. ok this was pretty tidious work and i doesn't always work when i have for example a class that needs to be passed and a callback would be overkill there. So i came up with a system used in most scripting languages. I didn't integrate it yet bc its not quite done. But the fundamentals are already layed out.

Here is an example:

Code: Select all

int main()
{
    localVar A;
    localVar B;
    A = 5;
    B = 1;
    A = A + 1;
    B = B - 6;
    printf("A = %i and B = %i\n", (int)A, (int)B);

    localVar C = AppFrame::string("Hello");
    C = C + AppFrame::string(" whats up");

    printf("Text is: %s\n", C.c_str());

    int First = 0;
    AppFrame::string second = "Test";
    AppFrame::SAttributeContainer Container;

    Container.Bind("Health", &First);

    Container.Bind("Name", &second);

    printf("Health: %i, Name: %s\n", (int)Container.getAttribute("Health"), Container.getAttribute("Name").c_str());

    Container.setValue("Health", 132);

    Container.setValue("Name", "Sudi");

    printf("Health: %i, Name: %s\n", (int)Container.getAttribute("Health"), Container.getAttribute("Name").c_str());

    Container.setValue("Health", "100");

    printf("Health: %i, Name: %s\n", (int)Container.getAttribute("Health"), Container.getAttribute("Name").c_str());
}
What do u think about that system? any good?

PS: this is no dreaming this actually already works^^
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

I believe strong type are actually an advantage, not a weakness. If something is an int for example, it says that it is only supposed to contain a number, that that number must be an integer. Those information are as relevant as the value stored within the variable. Removing them or making them changeable can break the code in whole new ways. They are plenty of way to convert types to other when the need arise, some even dangerous in their uses. In short, generic types are good, but only for prototyping and should be avoided when you want to convey information about a type. :)
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

...
Last edited by Seven on Sun Jan 25, 2009 5:13 am, edited 1 time in total.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

so, enough rambling..... a simple question for you now. Have you considered binding not the variable, but a function to the 'Health" attribute so that you can validate and or react to the variable setting?
Nice idea...i did it by adding a callback function that is called when ever the attribute is changed.

Code: Select all

localVar a;
a.addCallback(callback);
a = 5; //callback is called.
This is also inside the container class.

but your idea about the registering the set/get methodsis actually a quite cool idea. i will try to make a container with that feature.

@Dorth
with my system the following is not possible

Code: Select all

localVar a;
a = 5;
a = irr::core::stringc("Hallo"); //The var will not be changed here bc irr::core::string is not of type int
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

...
Last edited by Seven on Sun Jan 25, 2009 5:11 am, edited 1 time in total.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

...
Last edited by Seven on Sun Jan 25, 2009 5:10 am, edited 1 time in total.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

wait what?

Code: Select all

localVar a;
a = 5;
a.setValue("100");
that would work with my method and is intended to be used with the conatiner as u see in my first post last command
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

...
Last edited by Seven on Sun Jan 25, 2009 5:11 am, edited 1 time in total.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

...
Last edited by Seven on Sun Jan 25, 2009 5:12 am, edited 1 time in total.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

Ok i just wrote a implemantation of ur idea with the set/getMethods

Code: Select all

class StringSetGet
{
public:
    class qBasic : public irr::IReferenceCounted
    {
    public:
        qBasic(irr::core::stringc name)
        {
            Name = name;
        }
        virtual irr::core::stringc getVar(void){return "NULL";}
        virtual bool setVar(const irr::core::stringc& value){return false;}
        irr::core::stringc Name;
    };

    template<typename qClass>
    class q : public qBasic
    {
    typedef bool (qClass::*setMethod)(const irr::core::stringc&);
    typedef irr::core::stringc (qClass::*getMethod)(void);
    public:
        q(irr::core::stringc name, qClass* c, setMethod set, getMethod get) : qBasic(name)
        {
            Set = set;
            Get = get;
            Class = c;
        }
        virtual irr::core::stringc getVar(void)
        {
            return (Class->*Get)();
        }
        virtual bool setVar(const irr::core::stringc& value)
        {
            return (Class->*Set)(value);
        }
        setMethod Set;
        getMethod Get;
        qClass* Class;
    };

    irr::core::stringc getAttribute(const irr::core::stringc& name)
    {
        for (irr::u32 i=0;i < Attributes.size();i++)
        {
            if (Attributes[i]->Name == name)
            {
                return Attributes[i]->getVar();
            }
        }
    }

    bool setAttribute(const irr::core::stringc& name, const irr::core::stringc& value)
    {
        for (irr::u32 i=0;i < Attributes.size();i++)
        {
            if (Attributes[i]->Name == name)
            {
                return Attributes[i]->setVar(value);
            }
        }
    }
    template<typename C>
    bool Bind(const irr::core::stringc& name, bool (C::*set)(const irr::core::stringc&), irr::core::stringc (C::*get)(void))
    {
        for (irr::u32 i=0;i < Attributes.size();i++)
        {
            if (Attributes[i]->Name == name)
                return false;
        }
        Attributes.push_back(new q<C>(name, (C*)this, set, get));
        return true;
    }

    bool unBind(const irr::core::stringc& name)
    {
        for (irr::u32 i=0;i < Attributes.size();i++)
        {
            if (Attributes[i]->Name == name)
            {
                Attributes[i]->drop();
                Attributes.erase(i);
                return true;
            }
        }
        return false;
    }
protected:
    irr::core::array<qBasic*> Attributes;
};

class Test : public StringSetGet
{
public:
    Test(void)
    {
        Health = 100;
        Bind("Health", &Test::setHealth, &Test::getHealth);
    }
    int testfunc(const AppFrame::SVar& var, const char& a)
    {
        printf("Variable is: %s\n", var.getValue().c_str());
        return 1;
    }
    int Health;
    irr::core::stringc getHealth(void)
    {
        irr::core::stringc s = irr::core::stringc(Health);
        return s;
    }
    bool setHealth(const irr::core::stringc& health)
    {
        sscanf(health.c_str(), "%i", &Health);
        return true;
    }
protected:
};

class Test2 : public Test
{
public:
    Test2(void)
    {
        Power = 100;
        Bind("Power", &Test2::setPower, &Test2::getPower);
    }
    int Power;
    irr::core::stringc getPower(void)
    {
        irr::core::stringc s = irr::core::stringc(Power);
        return s;
    }
    bool setPower(const irr::core::stringc& health)
    {
        sscanf(health.c_str(), "%i", &Power);
        return true;
    }
protected:
};

int main()
{
    Test t;
    printf("Health: %i\n", t.Health);
    t.setAttribute("Health", "35");
    printf("Health: %i\n", t.Health);
    t.setAttribute("Health", "1");
    printf("Health: %i\n", t.Health);
    t.setAttribute("Health", "2");
    printf("HealthString: %s\n", t.getAttribute("Health").c_str());

    printf("--------------------------------------------------------------\n");

    Test2 t2;
    printf("Health: %i\n", t2.Health);
    t2.setAttribute("Health", "35");
    printf("Health: %i\n", t2.Health);
    t2.setAttribute("Health", "1");
    printf("Health: %i\n", t2.Health);
    t2.setAttribute("Health", "2");
    printf("HealthString: %s\n", t2.getAttribute("Health").c_str());


    printf("Power: %i\n", t2.Power);
    t2.setAttribute("Power", "35");
    printf("Power: %i\n", t2.Power);
    t2.setAttribute("Power", "1");
    printf("Power: %i\n", t2.Power);
    t2.setAttribute("Power", "2");
    printf("PowerString: %s\n", t2.getAttribute("Power").c_str());
}
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

...
Last edited by Seven on Sun Jan 25, 2009 5:10 am, edited 1 time in total.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

...
Last edited by Seven on Sun Jan 25, 2009 5:09 am, edited 1 time in total.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

ok i guess u got it all wrong.
i was taking about comunication between entities or the map editor. there u normaly don't need any virtual functions or anything. because the other class doesn't know at all how the other class looks like. Same with the map editor. the editor doesn't know how the class looks like. of course i can implement some simple types like int,float,string,vector,color but over all that is not what i want. i want it to be really independant of any class and rules. so i guess we are talking two different ways.
and btw. my just invented implemantation looks a little bit better than yours 8)
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

it wasnt a competition for me, just a chance to see another idea. thanks for the preview. I always enjoy seeing another point of view, good and bad.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

don't get me wrong but i think we both tried to accomplish different things in the first place.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Post Reply