• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Sneftel

Outboard component-based entity system architecture

106 posts in this topic

Quote:
Original post by Sneftel
Actually, I think this system is probably more amenable to parallelization than the standard component design. If you can't come up with enough subsystems to give all your cores something to do, just split a subsystem update across multiple cores. That's probably a good idea regardless, since different subsystems will eat up different-sized CPU slices. (This is assuming your subsystem updates can be parallelized; if they can't, you're screwed regardless of which design you go with). The key here, I think, is a job-based as opposed to a thread-based model, which Sony's been trying to convince people to go with anyway.


Creating a good parallelization design doesn't mean that you design sub systems to live on a thread/cpu. I don't really feel the component model will ever lend itself well to working on multiple threads. If there are any links to the outside world even if its loosely coupled then, in my opinion, the design of the system is flawed for multiple cpus/threads. Parallelization works best when you work in a functional model. Take input, transform input, create output. You can then take a bunch of these functions queue them up and send them off to do work. This allows one subsystem to use multiple CPU's/threads. The real work being done by functions and the subsystem handles setting up the data to be processed and any interaction with any other systems.

For example, if you have an AI subsystem then a good way to parallelize it is to create functions that perform work (i.e) chunk the world data into a buffer and send it off to a thread/cpu to find a path through it. You could have 10 of these working at once. As long as you can design your AI subsystem can defer looking for the best path until the threads are finished processing it.

It's kind of like programming in a purely functional language. If you know a function has no side effects then you know its ripe for parallelization.

I love all the different forms of component design but the beauty of their design is how well they can glue into different systems. I don't think trying to force them to be parallel is going to be a good clean solution. I feel it's better to separate the communication/interaction with the components/systems and the real grunt processing into functions.

This reminds me of the Tim Sweeney - The next generation of programming languages Where he shows statistics on how much code/time is spent in game play systems and how much code/time is spent on hard numerical crunching. The numerical crunching part is where you want to multi-thread the game play systems should be able to have references to shared data or events wherever they want.

-= Dave
0

Share this post


Link to post
Share on other sites
Well i had a quick look at the thread post and not at the rest of it so objectively here is my idea of a component based architecture for systems:

// System base class (used for Video or Audio subsystems etc)
class System { };

struct NamedIndex
{
int index;
string name;
};

// Holds a database of named and indexed systems
class SystemDatabase
{
private:
map <NamedIndex, System> mSystems;

public:
// registers a system with the database
void SetSystem (string name, int index, System * system) { }

// gets a system
template <class T
T * GetSystem (string name, int index = 0) {
Entry e = { index, name };
map <Entry, System>::iterator i = mSystems.find (e);
if (i == mSystems.end ())
return 0;
return dynamic_cast <T *> i->second;
}
};

// Sub class of System
class SceneGraph : public System
{
public:
SceneGraph (SystemDatabase * db) {
db->SetSystem ("scene", 0, this);
}
};

// to access a system
int main ()
{
SystemDatabase db;
SceneGraph * graph = new SceneGraph (db);

if (db->GetSystem ("scene", 0)) {
printf ("Yay it worked");
}
}


While this still allows objects to depend on other systems, it separates them from the object itself by having to ask the database for a type of system and it giving it whatevers there.

As for components and entities:

class Component;

// This collection of components abstracts it away from what object it is actually in (which may be a bad thing i dunno)
class ComponentCollection
{
private:
map <NamedIndex, Component *> mComponents;

public:
// sets a component (in implementation)
void SetComponent (string, int idx, Component * c)
{
// ... add component
c->mParent = this;
}

void Update (double dt);
};

class Component
{
private:
ComponentCollection * mParent;

public:
Component (ComponentCollection * parent);
};

// entity
class Entity : public ComponentCollection { };


Having a parent component collection member variable allows them to have a look at the other components by asking the collection for the object under the desired name such as
mParent->GetComponent <SceneNode> ("scene_node", 0)->Move (x, y, z);
0

Share this post


Link to post
Share on other sites
Quote:
Original post by David Neubelt
Creating a good parallelization design doesn't mean that you design sub systems to live on a thread/cpu. I don't really feel the component model will ever lend itself well to working on multiple threads. If there are any links to the outside world even if its loosely coupled then, in my opinion, the design of the system is flawed for multiple cpus/threads. Parallelization works best when you work in a functional model. Take input, transform input, create output. You can then take a bunch of these functions queue them up and send them off to do work. This allows one subsystem to use multiple CPU's/threads. The real work being done by functions and the subsystem handles setting up the data to be processed and any interaction with any other systems.

Yes, this is what I was talking about WRT a job-based instead of thread-based system.
0

Share this post


Link to post
Share on other sites
using the observer pattern, just wondering how people are handling this notify subject changed callback.

eg.


class Component
{
}

class ComponentA : public Component
{
void SomeFunction()
{
NotifyObservers(?);
}

void SomeOtherFunction()
{
NotifyObservers(?);
}
}

class ComponentB : public Component
{
void NotifySubjectChanged(Component* component, ?)
}




supposed ComponetB is an observer of ComponentA, but component B want to know different information based on if SomeFunction or SomeOtherFunction was called on ComponentA.

hence, some additional event info needs to be sent, i guess this should be an event id. It would be nice if i could just send through the pointer of the function that was called but c++ you cant just cast function pointers to void* unfortunately.

any one have any good ideas what to do here?
0

Share this post


Link to post
Share on other sites
Quote:
Original post by supagu
using the observer pattern, just wondering how people are handling this notify subject changed callback.

eg.

*** Source Snippet Removed ***

supposed ComponetB is an observer of ComponentA, but component B want to know different information based on if SomeFunction or SomeOtherFunction was called on ComponentA.

hence, some additional event info needs to be sent, i guess this should be an event id. It would be nice if i could just send through the pointer of the function that was called but c++ you cant just cast function pointers to void* unfortunately.

any one have any good ideas what to do here?



Well my quickest solution would be to create event classes inherited from a base event class and pass the base event class around to Notify objects of changes. I don't think you should have to pass the entire component for every change.


class BaseEvent
{
BaseEvent(int type, int source, int dest);
int eventType;
int senderId;
int receiverId;
};

class DerivedEvent1 : public BaseEvent
{
DerivedEvent(double information);
double derivedInformation;
};

class DerivedEvent2 : public BaseEvent
{
DerivedEvent(double information1, double information2);
double information1;
double information2;
};

class ComponentA
{
void SomeFunction()
{
BaseEvent *event = new DerivedEvent1(some_info);
NotifyListeners(event);
}

void SomeOtherFunction()
{
BaseEvent *event = new DerivedEvent2(some_info, some_other_info);
NotifyListeners(event);
}
};

class ComponentB
{
void NotifySubjectChanged(BaseEvent *event)
{
switch(event->eventType)
case EVENT_FLY:
{
// cast to specific event here
DerivedEvent1 devent = static_cast<DerivedEvent1*>(event);

// use information contained in derived event here

break;
}
...
}
};

0

Share this post


Link to post
Share on other sites
Can't you just do something like:


class observer {

public:

void notify(unsigned int event_type, entity* e);

};

class entity {

public:

void register_observer(unsigned int event_type, observer* o) {

m_observers[event_type]->push_back(o);

}

private:

std::map<unsigned int, std::list<observer*>*> m_observers;

};



Sure it's slightly oversimplified, but you could alter the map to be a map<unsigned int, map<observer*, void (*function)()> >, that way you get function pointers and only notify observers that care about certain event types. I'm probably overlooking something obvious though.
0

Share this post


Link to post
Share on other sites
I really, really dislike the event_id + event_params + giant_switch_statement approach to event notification. It's brittle, it defeats compile-time checking, it's difficult to maintain, it leads to long-simmering bugs. If there are two different events, they should be different objects.


class Entity
{
public:
event<float> CharacterJumped; // float height
event<Color const&, PantsSize const&> CharacterBoughtJeans;


void Jump(float height)
{
...
CharacterJumped.Invoke(height);
}

void BuyJeans(Color const& color, PantsSize const& pantsSize)
{
...
CharacterBoughtJeans.Invoke(color, pantsSize);
}
}




The system I've shown here uses my custom event library, but there are plenty of others if you want something more widely adopted. The important thing is not to take the C route of tossing type-safety out the window the moment you step outside the procedural programming paradigm.
0

Share this post


Link to post
Share on other sites
Just a thing. I´m following the subsystem abstract logic and component is just data idea.

I have wrote my first component RenderComponent, wich logic (I don´t have any lógic) is abstracted by RenderSubsytem. Subsystem also owns manages comopnent instances (creating and removing).

Now I would like to write a LightComponent, but I don´t know where to put them. Should I create a LightSubsystem (it seems a bit verbose), should I use the RenderSystem for it too? (I don´t see any logic in this components, I mean, RenderComponent, LightComponnet).

Any idea will be wellcomed, I´m a bit lost,
HexDump.
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Lord_Evil
What about this approach:

The entity would be a container for data-components, i.e. a transformation component (position, orientation etc.), a visual component (mesh, textures etc.), ...
Subsystems take the role of behaviour-components but there's only a single instance. Entities are then processed in a loop which works on whatever list may be appropriate for the subsystem. Data that is needed per entity but only within the subsystem could be stored using the decorator pattern.


This is almost exactly what I used to do with my Python-based engine, though at the time I wasn't yet "enlightened" and tried to create a unified scene graph using this idea. It's actually quite elegant to implement in Python, since you can add attributes to objects dynamically, and overload the attribute-setting method.

I'm actually currently in the process of trying to design a new scene / entity / whatever management system for my game, whose engine is loosely based on my old engine. I have a couple of different ideas - all component-based - I want to design and evaluate further:

1. Very similar to what's described above, but on a higher level, ditching the unified scene graph idea.
2. Components define behaviour, while entities contain arbitrary components and their (possibly shared) data.
3. Entities are solely containers for components, while components contain both behaviour and data.

In all versions, communications would be done with signals (an implementation of the observer pattern with a twist), just the location of signals would change; either in the entity or in relevant components.
0

Share this post


Link to post
Share on other sites
Hi, hopefully this thread hasn't died out too much.

I've just finished reading through the thread, and it sounds very interesting. I was aware of component based design before, but never thought about the idea of components attaching themselves, rather than explicitly attaching components to entities.

Recently I've been messing about making a little asteroids like game - for fun, seeing as I don't have much time now that I'm at uni. Now at the moment, it only has Asteroids that can fly around the screen and does not use a component based design - but I'd like to try and apply one now.

At the moment I have an Actor class which has position and velocity. Asteroid extends this Actor class, and adds a bit more information - Orientation, Health and Size.

Actors can also have controllers applied, and Asteroid has a ScreenWrappingController that makes sure that after the actor has updated (moved position by velocity) that the entity is within screen bounds.

As for rendering, I use a visitor pattern that visits everything that is IRenderable. When it is visiting an Asteroid, the visitor checks to see if it's drawn this Asteroid before. If it has /not/, it creates a quad on the fly (I know... should use batching, but that's another topic) and loads an Asteroid texture and forever on uses this quad to render with.

Now this is a rather simple example at the moment, but how would you tie all of this together? What I think, if I'm understanding correctly is: Asteroid is a composition of an ActorComponent (think SpatialComponent but with a bit logic?), and maybe a DamageComponent - and the actor component is controlled by a ScreenWrappingController (maybe later refactored to a BoundryRestrictingController). In terms of Rendering, the creation of an Asteroid causes an QuadGeometryComponent to be created, requesting an asteroid image from some type of ResourceManager (but only storing a somewhat weak reference to this).

I suppose now at render time a Visitor pattern is not required, here we would now just request the GraphicsSubsystem to render all of its components - but how does it know the location of these components? I understand that the SpatialSubsystem should listen to the GraphicsSubsystem to ensure the creation of a GraphicsComponent, so a component would definitley be created - but how does the QuadGeometryComponent actually get to this component, without becoming coupled with the SpatialSubsystem in some way?

I have a feeling this may be why people advocate simply throwing positional data into the Entity container...

Sorry if this post seems a bit of a ramble, I will hopefully be able to clean it up later with an edit :)
0

Share this post


Link to post
Share on other sites
I would be specifically interested in whether you also include very abstract concepts in your entity system, like a statistics object or a path planner, or do you use this system only for "real" game objects. While it might have some advantages to include everything, for example a GUI could react on a "take damage" message for a unit and display a warning, I think this might also get complicated.

I'm currently experimenting with such a system and would like to know what advantages or disadvantes of either approach you see. Thx!
0

Share this post


Link to post
Share on other sites
Ok, I've gotten further with moving my design over to a component based one. Now I have a ResourceManager to request textures and geometry data. I have 2 main components at the moment: GeometryComponent, DamageComponent. GeometryComponent creates/requests the quad mesh and also loads the texture of my asteroid, and damage component is there to allow the asteroid to explode, whenever I get round to writing a particle system or something.

I also allow controllers to be placed on my Entity class, but I'm not sure this is the best approach. When creating my asteroids, this is what I'm doing:


for(int i = 0; i < amountOfAsteroids; i++) {
EntityDefinition asteroidDefinition = new EntityDefinition {
ComponentTypes = new List<Type> {
typeof(GeometryComponent),
typeof(DamageComponent)
},
Properties = new SpaceGame.Components.Properties()
};

Vector2 position = new Vector2( (float)(randomGenerator.NextDouble() * 800),
(float)(randomGenerator.NextDouble() * 600));
asteroidDefinition.Properties.Add("position", position);

Entity asteroid = CreateEntity(asteroidDefinition);
asteroid.Controller = new LambdaController(entity => entity.Position += new Vector2(1, 0));
}





Obviously my asteroids will do more than slide 1 unit to the left every second in the future, but this is just to test it works. But controller doesn't seem like it's going to be very useful in the future... I thought about making this some type of component, but then it wouldn't be very generic.

Also, how can I now enforce that the Entity is only within screen bounds? I think it may be best at the moment to write a controller specific to Asteroids - an asteroid moving controller that implements both movement, and screen wrapping - but this seems a little bit too complex for a small controller. The controller also needs some way to tell the renderer to render the mesh in 2+ locations to give the illusion that it's wrapping round the screen.



Edit:

Ok, so I've been playing around some more, and my self an Asteroid component and I think I like this a little more, but I'm still not 100% confident about it. The problem now is that the Asteroid component has data about how the Asteroid should be displayed - the rotation and scaling of the Asteroid.

Now Geometry components don't depend on Asteroid components, so creating an Asteroid when a Geometry component is created doesn't make sense. So the Geometry component can't really depend on the Asteroid at all, or it's useless for rendering say... items, nebulas, the players ship, etc.

I think the main, larger problem here is how can components co-ordinate an Entity's state? Every example I can contrive can be solved with events in some way, but for some reason I can't see a nice way to solve this problem.

I'll stop forum'ing now, and get some sleep, maybe the solution will come to me in the morning :)

Any ideas?

[Edited by - Cycles on December 12, 2007 8:53:50 PM]
0

Share this post


Link to post
Share on other sites
I've been reading this thread hoping to learn something, but I think I'm more confused than when I started.

One thing I have noticed is the need for positional information in both the physics component and the rendering component. However no-one seems to have just merged the components and had the physics subsystem and the rendering subsystem act as database 'views' into the entity database (in my pseudo design my entities as basically HashMaps, and contain arbitrary State objects). Of course, I'm probably missing something important...

One thing I am confused about is how to control my space ship entity (it's click-to-move rather than direct control), since the physics system will control all movement, to get the ship to move you need to add a force somewhere. I just don't get how all the components fit together.

Regards
elFarto
0

Share this post


Link to post
Share on other sites
hmm... don't you think this is going a bit too far? I mean, by now, we already have: entities, components, systems and subsystems, and with that, people is clearly having problems understanding mutual relationships between these different elements. I myself don't know very well in which direction to go, because, so far, many of the solutions presented here would not allow some things I want to do.

Remember, one of the theorical good things about componentized entities was to avoid the traditional, bloated hierarchical entities. And I think we should move in the direction to see how everything fits in a real scenario.

For example: many have said that only allow one instance of a given component type inside a single entity; but, given that a "weapon" would be a component, what if I want an entity to have multiple weapons?

In a game like Quake, I think a player entity could be broken in the next components:

-quake player entity
-spatial component (position, rotation)
-physics (velocities, collision detection) component
-user input component
-AI component
-3rd person character mesh component (mesh id, animation frame)
-3rd person weapon mesh component ( mesh id, character mesh bone)
-1st person character mesh component (mesh id, animation frame)
-1st person weapon mesh component ( mesh id, character mesh bone)
-health component (health value)
-weapon1 component (ammo)
-weapon2 component (ammo)
-weapon3 component (ammo)
-weapon4 component (ammo)
-Shield component (remaining time)
-cloaking device component (remaining time)
-Score component (num of kills, num of deaths, etc)

Somehow, I know I would need all that stuff for a quake like entity, but they're already quite a number of components for a single entity... and we're talking about the ultra simple old quake guy... modern games might need much more than that.

Agree? disagree? how to handle them? what happens if the guy receives a shot? who is notified first? the shield component if enabled? or the health component that looks for the shield component?, or should the mesh render components be aware that there's a "cloaking device" component enabled to render in a different way?

I think this is worth discussing.

[Edited by - vicviper on December 13, 2007 12:01:29 PM]
0

Share this post


Link to post
Share on other sites
I am jumping in here late, but a quick comment in response to Sneftel's OP.

Quote:
Original post by Sneftel
There have always been a few things I didn't like about the component-based model.

* Components have difficulty finding other components in the same Entity. Given an AnimationComponent which requires a PathfindingComponent to use, often it's necessary to manually iterate through the list of Components, dynamic_casting each one until you get a hit, or else to complicate the factory with details of what component needs to know about what, or the Entity with specific typed Component members for direct access.

* Components have difficulty finding the same components in other Entities, and their associated game-wide subsystems. The PathfindingComponent needs to know at least about other Entities' PathfindingComponents, or (more likely) a GameWidePathfindingSystem. The former can require a lot of iteration and dynamic_casting; the latter requires either some pretty serious arrow chains, or singletons/globals.


This isn't anything earth-shattering, but I thought I'd throw it in... We are using a component-based system where logic components publish named attributes, actions, and events, so you don't have to "find" other components, you just have to perform an operation using a name.

For example, if you want to adjust an entity's "speed", you don't have to find the component that publishes it because the entity itself knows how to deal with that:

float speed = entity->GetAttribute("ATT_SPEED");
entity->SetAttribute("ATT_SPEED", speed);

In our system, attributes kept to a small set of fairly primitive types (strings, vectors, ints, floats, bools, that sort of thing), but you could allow it to pass pointers around so that like components on different entities could locate each other.

We can subscribed to attribute changes...

entity->SubscribeToAttributeChange("ATT_SPEED", someFunctionPtrTypeThing);

...or to any published event.

In the system we use, there is actually a database of all published attributes, events, actions, etc., which allows for development tools to bring up lists of published names so that you can see what's available at dev time.

Then there are renderable components which can't publish attributes, but which look for published attributes. So if you wanted a component to draw a HUD, for example, you would need a HUD logic component to keep the details straight, and a renderable component to draw everything, pulling data from the logic component.

It's sort of an MVC component-based architecture.
0

Share this post


Link to post
Share on other sites
Quote:
Original post by vicviper
hmm... don't you think this is going a bit too far? I mean, by now, we already have: entities, components, systems and subsystems, and with that, people is clearly having problems understanding mutual relationships between these different elements. I myself don't know very well in which direction to go, because, so far, many of the solutions presented here would not allow some things I want to do.

Remember, one of the theorical good things about componentized entities was to avoid the traditional, bloated hierarchical entities. And I think we should move in the direction to see how everything fits in a real scenario.

For example: many have said that only allow one instance of a given component type inside a single entity; but, given that a "weapon" would be a component, what if I want an entity to have multiple weapons?

In a game like Quake, I think a player entity could be broken in the next components:

-quake player entity
-spatial component (position, rotation)
-physics (velocities, collision detection) component
-user input component
-AI component
-3rd person character mesh component (mesh id, animation frame)
-3rd person weapon mesh component ( mesh id, character mesh bone)
-1st person character mesh component (mesh id, animation frame)
-1st person weapon mesh component ( mesh id, character mesh bone)
-health component (health value)
-weapon1 component (ammo)
-weapon2 component (ammo)
-weapon3 component (ammo)
-weapon4 component (ammo)
-Shield component (remaining time)
-cloaking device component (remaining time)
-Score component (num of kills, num of deaths, etc)

Somehow, I know I would need all that stuff for a quake like entity, but they're already quite a number of components for a single entity... and we're talking about the ultra simple old quake guy... modern games might need much more than that.

Agree? disagree? how to handle them? what happens if the guy receives a shot? who is notified first? the shield component if enabled? or the health component that looks for the shield component?, or should the mesh render components be aware that there's a "cloaking device" component enabled to render in a different way?

I think this is worth discussing.


Conceptually, I don't think of components as something you'd really want to be adding and removing at runtime. Practically, there tends to be a lot of overhead involved in doing so.

At any rate, there's no clear advantage to having weapons and ammo be components. If I were doing something like Quake I'd probably just have an "Inventory" component which contained weapons, ammo, shields, etc. Maybe another component to keep track of what's currently equipped and proxy onTakeHit and onFire events.

0

Share this post


Link to post
Share on other sites
Quote:
Original post by vicviper
***snip large post***


Another thing I've noticed is a split between 'engine components' and 'game components'. So the first 4 on your list are engine components (they're directly related to a capability of the game engine). The next 4 should really just be one render component.

The rest however, are game components (i.e. implement game logic/content) and I still haven't figured out what to do with those.

Regarding the component/subsystem thing. I believe that they are 2 sides of the same coin. To me, a component means that the logic would be incorporated into each entity, where as a subsystem indicates there's just 1 instance of it (this also kinda implies that the entities are purely data).

Regards
elFarto
0

Share this post


Link to post
Share on other sites
Quote:
Original post by vicviper
For example: many have said that only allow one instance of a given component type inside a single entity; but, given that a "weapon" would be a component, what if I want an entity to have multiple weapons?


In that case, you can have a WeaponCollectionComponent that maintains the list of WeaponComponents the player has, along with which WeaponComponent is currently active, etc.
0

Share this post


Link to post
Share on other sites
Quote:
Original post by vicviper
For example: many have said that only allow one instance of a given component type inside a single entity; but, given that a "weapon" would be a component, what if I want an entity to have multiple weapons?
Then "weapon" shouldn't be a component; "weaponry" should, or (perhaps too abstracted) "inventory".

Quote:

-spatial component (position, rotation)
-physics (velocities, collision detection) component
-user input component

"User input", IMHO, is sort of a strange thing to make into a component; I see it as an outside system sending calls to a particular entity.

Quote:

-3rd person character mesh component (mesh id, animation frame)
-3rd person weapon mesh component ( mesh id, character mesh bone)
-1st person character mesh component (mesh id, animation frame)
-1st person weapon mesh component ( mesh id, character mesh bone)

Blech! More likely, a single "graphics" component.

Quote:

-weapon1 component (ammo)
-weapon2 component (ammo)
-weapon3 component (ammo)
-weapon4 component (ammo)
-Shield component (remaining time)
-cloaking device component (remaining time)

See "weaponry"/"inventory" above.
Quote:

-Score component (num of kills, num of deaths, etc)

Somehow, I know I would need all that stuff for a quake like entity, but they're already quite a number of components for a single entity... and we're talking about the ultra simple old quake guy... modern games might need much more than that.

Your idea for components has much teenier granularity than mine. I don't think that taking all the character's weapons and all his stats and all his meshes and throwing them into a flat list of "components" is a good idea. A "component", to me, is an entity-specific delegate* for accomplishing a particular area of the entity's functionality. Components should have data structures that are as complex as they need to be. The complexity should be maintained within the component.


*I don't mean that in the bound-function-pointer sense of the word.
0

Share this post


Link to post
Share on other sites
a weapon is fluff on the side of the engine. the engine shouldnt know about things like multiple instance game items.

The game should be defining an 'item' or usable item class(s) which be kept in an item inventory.

class ItemInventory;

// Item base class
class ItemBase
{
private:
ItemInventory * parent;

public:
virtual void Use (void) = 0; // etc etc
const char * Name (void);
};

// item inventory
class ItemInventory : PropertyObject
{
private:
map <string, vector <ItemBase *>> item_categories;

void AddItem (string category, ItemBase * item);
};

// adds a weapon item and sets it to be the primary
ItemInventory inv;
Weapon * shotty = new Weapon ("shotgun");
inv.AddItem ("weapons", shotty);
inv.SetProperty ("prim-weapon", shotty); // from PropertyObject class




0

Share this post


Link to post
Share on other sites
Quote:
Original post by smitty1276
[ lotsa stuff ]

I like this approach. One thing that I notice about it, though, is that it is basically a reimplementation of OOP within C++, one which supports runtime-composed objects. My thought, therefore, is that the first thing to do is to come up with a good framework for runtime-composed objects in C++, independent of entities and components and whatnot.

More to come, gotta run.
0

Share this post


Link to post
Share on other sites
In regards to smitty's post - it seems like a nice simple way to tackle the problem, but aren't you making a pretty big sacrifice: compile time checking? Maybe there is some real magic behind the scenes, but I can see that as being a predominantly runtime system...

My latest iteration of this is to now declare Entity's like this:


public class Asteroid : Entity
{
public Vector2 InitialVelocity { get; set; }

Controllers.ScreenWrappingController swc = new SpaceGame.Controllers.ScreenWrappingController(new System.Drawing.Size(800, 600));

public Asteroid(World manager) : base(manager)
{
AddComponent(typeof(Components.Damage));
AddComponent(typeof(Components.Geometry));
AddComponent(typeof(Components.MoveableComponent));
}

public override void Initialize()
{
Components.Geometry geometry = RequestComponent<Components.Geometry>();
geometry.CreateQuad(new Rectangle(-1, -1, 1, 1));

Components.MoveableComponent moveable = RequestComponent<Components.MoveableComponent>();
moveable.Velocity = InitialVelocity;
}
}



Then you just create an Asteroid as:

Entities.Asteroid asteroid = new SpaceGame.Entities.Asteroid(this)
{
Position = position,
Rotation = (float)(randomGenerator.NextDouble() * 2 * Math.PI - Math.PI),
Scale = (float)(randomGenerator.NextDouble() * 50 + 10),
InitialVelocity = velocity
};

InjectEntity(asteroid);


InjectEntity(Entity) is a method on my World class that simply notifies all component subsystems that an Entity has been added, and they then check the Entities requiredComponents as to whether they should act on the creating an Entity.

The Entity is then initialized, and is able to retrieve it's components as it needs then, and seed them appropriatley.

In this model, the Entity acts as a specific "coordinator", and would be responsible for handling certain messages (I.e. when a Damage component reports itself as depleted/destroyed), and routing them to other components as needed.

Any ideas on this?
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
I like this approach. One thing that I notice about it, though, is that it is basically a reimplementation of OOP within C++, one which supports runtime-composed objects. My thought, therefore, is that the first thing to do is to come up with a good framework for runtime-composed objects in C++, independent of entities and components and whatnot.


Quote:
Original post by Cycles
In regards to smitty's post - it seems like a nice simple way to tackle the problem, but aren't you making a pretty big sacrifice: compile time checking?


Yes and mostly yes.

One of the uses of the system is that it allows non-developers to create content... entire AI behaviors (of widely varying complexity) can be visually "scripted" for entities, using nothing more than basic operations on named attributes. So, yeah... it's definitely a way of exposing an OOP-like interface to non-developers who wouldn't even recognize the term. It definitely allows for class inheritance and that sort of thing from the non-developers perspective--entity types can be drived from others and inherit their attached components, etc.

0

Share this post


Link to post
Share on other sites
I'm curious how people handle scenegraph integration with a component based system. Usually things like Effect, Position, Cameras, etc are part of a scene graph but they also make sense as components.

I was thinking of arranging my entities hierarchally such that the entities double as nodes. I found traversal difficult with this method.

The other approach I tried was maintaining separate hierarchies for things like world transforms.


class WorldTransform : public IComponent
{
public:
Matrix Transform()
{
Matrix t = transform_;
if(parent_)
{
t *= parent_->Transform();
}
return t;
}
private:
Matrix transform_;
boost::shared_ptr<WorldTransform> parent_;
};


This worked alright for world transforms but doesn't seem to apply cleanly anywhere else. For example, I have no idea how cameras, and effects might fit in.
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by smitty1276
[ lotsa stuff ]

I like this approach. One thing that I notice about it, though, is that it is basically a reimplementation of OOP within C++, one which supports runtime-composed objects. My thought, therefore, is that the first thing to do is to come up with a good framework for runtime-composed objects in C++, independent of entities and components and whatnot.

More to come, gotta run.

I couldn't leave well enough alone.
0

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  
Followers 0