eigenbom







@eigenbom





Level 10@eigenbom Re: moonman « Reply #14 on: October 08, 2011, 11:08:42 PM »



I'm not sure if anyone's interested in technical details, but I'll write a few more words on the design just in case. I mocked up some of this design in code the last couple of days.



Every character, item, weapon, effect, gui element, etc., in moonman is an Entity. An Entity is composed of Attributes and Properties. Attributes are key-value pairs which specify the shared data of an entity, and the sum of properties in an entity specify its capabilities. For instance, an npc in the game might be created as follows:



Code: // script

npc = create_entity {x=0,y=0,vx=0,vy=0,onground=false,sprite="someguy.png"}

npc:add_property(physics)

npc:add_property(walker)

npc:add_property(renderable)

npc:add_property(ai_controller)



Each property has an update and onMessage function, and has access to the shared data in an entity. e.g.,



Code: // c++

class PhysicsProperty {

public:

virtual void update(Entity* e, double dt){

e->attrib(x) += e->attrib(vx)*dt

// ...

}

}



The attributes are accessible by all the properties because there is commonality between them (e.g., the Renderable property needs the x and y coordinates to draw the npc in the right location.) This simplifies things, at the cost of being easier to shoot yourself in the foot (so as rule of thumb: each attribute should be modified by only one property).



An attribute in my engine is implemented as a boost::variant: Code: typedef boost::variant<bool,int32,float,std::string> Attribute;

Each attribute and property is assigned a unique integer id. This is for efficiency reasons (an integer lookup is quicker than a string lookup and an integer is smaller than a string). However, because users can add new attributes and properties, the assigning of ids is done dynamically. E.g., a user can add a new entity attribute of type float, with a default value of 1.5., by writing

Code: // lua

id1 = register_attribute_float("foo",1.5)

The registry returns an attribute id that the script can store (for this instance) to refer to the attribute, e.g.,

Code: // lua

some_entity.attrib(id1) = .5

... although I'm investigating Lua meta-tables to see if I can allow the much simpler...

Code: some_entity.foo = .5



In regard to the multiplayer aspect the server and client may be running different scripts/mods (or have them loaded in different order), which means that the attribute id's may be different. Hence, the client needs to store an mapping between the servers ids and the clients ids. This can be done fairly efficiently just by recording which blocks of ids belong to which mods. Saving a game world to disk is also simplified using a global id system.



I've never built a game this way, I typically just hard hard-coded all the classes into some inheritance hierarchy, so I find it very interesting to build types dynamically. It seemed to work for Dungeon Siege, Neverwinter Nights, etc, but I'm just a lone coder .. so we'll see whether I'm consumed by the extra work required or not! @kamac cheers!I'm not sure if anyone's interested in technical details, but I'll write a few more words on the design just in case. I mocked up some of this design in code the last couple of days.Every character, item, weapon, effect, gui element, etc., in moonman is an. An Entity is composed ofand. Attributes are key-value pairs which specify the shared data of an entity, and the sum of properties in an entity specify its capabilities. For instance, an npc in the game might be created as follows:Each property has anandfunction, and has access to the shared data in an entity. e.g.,The attributes are accessible by all the properties because there is commonality between them (e.g., the Renderable property needs the x and y coordinates to draw the npc in the right location.) This simplifies things, at the cost of being easier to shoot yourself in the foot (so as rule of thumb:).An attribute in my engine is implemented as a boost::variant:Each attribute and property is assigned a unique integer id. This is for efficiency reasons (an integer lookup is quicker than a string lookup and an integer is smaller than a string). However, because users can add new attributes and properties, the assigning of ids is done dynamically. E.g., a user can add a new entity attribute of type float, with a default value of 1.5., by writingThe registry returns an attribute id that the script can store (for this instance) to refer to the attribute, e.g.,... although I'm investigating Lua meta-tables to see if I can allow the much simpler...In regard to the multiplayer aspect the server and client may be running different scripts/mods (or have them loaded in different order), which means that the attribute id's may be different. Hence, the client needs to store an mapping between the servers ids and the clients ids. This can be done fairly efficiently just by recording which blocks of ids belong to which mods. Saving a game world to disk is also simplified using a global id system.I've never built a game this way, I typically just hard hard-coded all the classes into some inheritance hierarchy, so I find it very interesting to build types dynamically. It seemed to work for Dungeon Siege, Neverwinter Nights, etc, but I'm just a lone coder .. so we'll see whether I'm consumed by the extra work required or not! Logged MoonQuest Devlog