Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

Zipster

Member Since 11 Mar 2000
Offline Last Active Yesterday, 12:05 PM
-----

Posts I've Made

In Topic: Component Design in Component Based Game Engine

30 April 2013 - 02:02 PM

Just to clarify, components shouldn't "contain" entities in the traditional sense. All the entities in the game should exist together in a flat structure, and the components should only store IDs to entities (there was also a recent article series on decoupling that covered this subject in particular).

 

Now say I have a GoldSubsystem and there is a function GetTotalGold, which is suppose to compute all the gold for a specific entity and its children. So if I input a village I get all the gold in the village + all the gold of all the players. Nothing is static here, so sometime in the future I may decide to remove the GoldComponent from the village, but then I should still get the total gold of all the players in the village.
 
In this design, there must be some way of iterating through entities that are contained within components, and to query these if they contain specific components. This suggests that there should be an interface on the components to support this behaviour. Or am I modeling this wrong?

You have the right idea, we just need to have the interfaces in the right place.

 

For this example, you can have the WorldComponent implement the IParent interface (it can be the parent of both villages and players), the VillageComponent implement both the IParent and IChild interfaces (it can be both the child of the world and a parent of players), and the PlayerComponent implement the IChild interface (it can be the child of both the world and villages).

 

You then create a ParentChildSystem which acts only on the components that implement these interfaces. Given a root object (such as the world or a village), you find all components on that entity which implement IParent. At the point, you then find all components across all entities that implement IChild, and reference any of the root object's IParent IDs. You then find all the IParent's on this new set of entities, and the IChild's on other entities that reference them, etc. It's basically a breadth-first search. Once you have the list of entities, the GoldSystem can find all the GoldComponents and tally them up, without concerning itself with parent/child relationships or hierarchy (since that's the ParenChildSystem's job).

 

The biggest downside here is that the generalized interfaces, combined with a lack of forward references from parent to child, can lead to objects being included that you didn't want, and rather inefficient searches (note the "all components across all entities" part of the search). The best way to fix this is to simply add the child IDs directly to the IParent component, and have the system keep the IParent and the IChild components in sync, as phil_t mentioned a few posts ago. It's still a BFS, except now you're not doing searches across all entities and components. This doesn't necessarily fix the pruning problem, where objects you don't want are returned in the search. As previously mentioned, there are different types of parent/child relationships, and you might only care about specific ones when doing certain searches. For instance, when counting gold, you probably don't want to consider objects that are just physically attached to the player or village, but perhaps objects that are actually "owned" by them. In that case, the interfaces can also expose what kind of relationship they are, and the search can prune them based on that.

 

If you want, you can also dispense with the interfaces altogether and have the GoldSystem know precisely which component types (i.e. WorldComponent, VillageComponent, PlayerComponent) it needs to query, as well as their exact relationships. For a small game this is the easiest approach, except you might find that some code gets duplicated as multiple systems end up querying the same parent/child hierarchies, since there is no interface type upon which to build a generalized solution.


In Topic: Component Design in Component Based Game Engine

29 April 2013 - 11:09 AM

I'm not sure if there's much benefit in having a general-purpose ChildComponent. As phil_t pointed out, there are a number of different types of parent-child relationships, and it's difficult to find a generalization of the logic and data required for each without dealing in the specifics of any particular type of relationship. If you do go down that route, I'd say you could store a parent ID at most, and then have utility methods to perform the typical get-children, get-siblings, get-parent, etc. operations. However anything beyond that and it would seem as though you're dealing in the particulars, i.e. does the parent "own" the children? Are they attached in a hierarchy? Are the children contained within the parent?

 

What you can probably do in lieu of having a special ChildComponent is create IChild and IParent interfaces that are implemented by the various components that need to use these relationships. Then you can build a set of utility methods (possibly a full system) that deals in these interfaces alone. Each component that implements these interfaces can do so in such a way that makes the most sense for that type of relationship, and they can have their own systems that augment the general-purpose interface with specific methods that make sense for their relationship.


In Topic: Reasons for wanting custom malloc or allocators?

25 April 2013 - 11:51 AM

Another reason is pure performance.

For example, if you know that you will allocate 1000 objects in a row and then delete them all at once, you can use a one-way allocator which creates space for all 1000 objects and then just constructs/destructs them as needed and blows away the entire allocation in one shot. This can be far faster than doing 1000 general-purpose allocations and helps alleviate things like fragmentation to boot.

Stack allocators can also be useful (where you can only free the most recently allocated object) and so on.

 

When I worked on console games, we would allocate all the memory upfront from the system and use our own allocator to divvy it out. It was a lot faster than going to the system for every allocation and allowed us to place more strict restrictions on memory usage, i.e. this level can only use 200MB, and if it goes above that then crash dump and trace where all the memory is going.


In Topic: Component Design in Component Based Game Engine

22 April 2013 - 04:34 PM

Should the systems be responsible for state logic (hard coded), or would this better be put into the data section of a component based system? One situation is when a LandComponent is not yet finished constructing a building. During this time the LandComponent should have a different set of attributes compared to when it's finished.
 
To me it seems as if there are two ways here:
 
1) Predefine/hard-code the known states of Land (Developed, Constructing, Empty), and then let the SubSystem shift values depending on current state.
 
2) Define states in the data, and let the LandComponentSystem implement a state machine.
 
Any other way of doing this? Comments regarding my two suggestions?

If any of the states confer some sort of special logic in the LandComponent that only applies to that particular state, then they'd have to be hard-coded somewhere in order for the component's code to act on that state (option 1). Otherwise you'd need to make the logic data-driven as well, i.e. a scripting system of some sort, but that's another subject altogether.

 

The exception is if the logic of each state follows some similar form that can be coded in a generic way, i.e. each state just corresponds to a population capacity modifier, and the logic to transition states isn't specific to the current state. Then the states can be purely data because they're not tightly coupled to state-specific logic, and you can write a single piece of logic that knows how to set the population capacity modifier and transition states (basically, option 2).


In Topic: Component Design in Component Based Game Engine

22 April 2013 - 12:13 PM

I'd be wary of having multiple systems modifying the same property of a Component. Instead, I would have one system that is responsible for setting the current population capacity based on various states (e.g. whether a building is in construction, how long has been since it was maintained, etc...).
 
Of course this doesn't necessarily mean you have a construction system, a run-down system (to track how long it's been since it was maintained), a population-setting system, etc.... They could all be different stages of the Update cycle of the same "building" system (assuming they all rely on the same set of components).

I wouldn't solve the issue of multiple systems modifying the same component value at the system design level, by only allowing one system access. One of the main reasons you completely isolate data and logic in this component design is to introduce a level of abstraction that allows the code structure to be independent from the data structure. However only letting one system modify a value couples the two structures together again and you lose the benefit of that abstraction.

 

Rather, I would solve the problem at the data level and use an approach that lets multiple systems modify a value in a well-defined way. You already touched upon such an approach with the various Modifier and Multiplier components. Generally speaking, you allow values to be backed by formulas, like x * A, (x + A) * B, etc., and allow systems to modify the inputs (A, B), whereas the constants (x) are sensible defaults or initial values. The formulas can have an arbitrary number of constants and inputs, and can vary per value depending on how you want systems to influence them. You don't necessarily have to implement such a system in the context of the component design, with individual components representing the various inputs and whatnot, since that seems as though it would get heavy with components for every input of every formula, and it's not really "game" code per se... however that's neither here nor there. The point is that systems aren't modifying raw values, but rather adjusting them in the context of modifiers/multipiers/bonues/etc., and you aren't gatekeeping them behind single systems. Best of both worlds.

 

Total amount would be the number of buildings of type x contained in this entity. I don't want a separate row for each type x building, but instead group them into a column (total_amount) instead.

An entity is a single building instance. What you're describing sounds like an entity to manage buildings, which could be the land entity (with a LandComponent) you mention later. However any given building instance wouldn't store the amount of its type. It would be redundant information on each building.


PARTNERS