Public Group

Data Driven Design: Part 2

This topic is 2188 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

So in continuation from my last post I was confronted with what seemed to be my problem with this methodology.

Your problem appears to be that you are suffering from design paralysis because you're trying to take in the entire scope of everything that could be considered data-driven design at all once, including complete existing implementations, so you can rebuild it yourself. This is bound to result in frustration and failure. You need to start small, and build systems that you need for your games. Reading other people's code can be interesting, but often lacking in a lot of critical detail about the why of various decisions that can easily lead you astray.

I looked over what I wanted to do and is now trying to split it into very small bites and take it a step at a time.

I was advised to look at parsing XML or JSON but I wanted to try something else first as I like visuals. Parsing, in my experience, is not that hard.

So I started designing a flat hierarchy structure which seems to be common for DDD software. From what I understand this design below should follow the philosophy of DDD.

The system is build up of Entities which consist of Components, each defining a behaviour or attribute that the entity can have. So an entity is defined by it's components and is otherwise an empty shell without behaviour or attributes.

Each Entity got an ID specified by a simple Int. Might change in the future of course. The ID is given when the Entity is born. It got a list of Components which is done by making a list that contains objects which implements IComponent. Every component will implement IComponent and if in the future every single Component needs a certain behaviour or attribute it can be implemented via the Interface.

In this case, since I want to just render a sprite on screen, I've made two component classes. The SpriteComponent and the MovementComponent. They don't contain any logic whatsoever only fields.

They both use objects from the SFML Framework which is also shown in this picture.

My goal this time around is simply to render a sprite on screen given X,Y Coordinates.

Am I on the right track?
Would you suggest different naming given what I want to achieve above?

The reason I called it "MovementComponent" is because I want it to signal that this entity can move from A to B, rather than PositionComponent which would indicate that it's stationary. (At least that's what I think, correct me if you feel it's backwards).

Now to handle Components and Entities I use Managers. Some seems to call them Systems, but if I understand it correctly it simply comes down to preference as they do the same thing.

In DDD you want to update things in pairs rather than in sequence. So instead of doing ABC, ABC, ABC which will have a horrible impact on performance, you do AAA, BBB, CCC and so on.

So for every component type you need a ComponentManager. The following design should illustrate it.

The EntityMgr holds a reference to one of each Component Manager which in turn will hold every single component of their type. They all implement the IManager Interface since they will all need their implementation of the Update() Method. So if in the future you want to extend the engine with more managers and component types this should be easy to follow.

The EntityMgr also creates entities and gives them an ID. The EntityMgr can also remove an entity and all of it's components when we don't need the entity any more. When Create is called it's supposed to put the components in their rightful manager. I am still debating the idea whether an Entity will just be there so that I can assemble it and its components from it's ID or if I should keep a reference for every single Entity in the EntityMgr.

Am I on the right track? And if so:

Which do you think would be the smartest in this case?

This could turn into a series of threads where I get from zero to hero

Edited by vipar

Share on other sites

Since there is nothing like an ECS Pattern, your approach is neither right nor wrong, but a few things:

I dont think you need different Managers for different Componentpools, first of all you don't want to write one for every new component and second I cant think of anything they would handle in different ways, in C++ I used a templateclass for the componentpool, so every pool can be used like Pool<ComponentType>, I believe there's something similar in C#

Now to handle Components and Entities I use Managers. Some seems to call them Systems

System usually process components, your managers just hold them, I would make this difference because you will have more then one system running on your components.

Every component will implement IComponent and if in the future every single Component needs a certain behaviour or attribute it can be implemented via the Interface.

This sounds very OOP like, some people will probably tell you that components shouldn't inherit anything.

In this case, since I want to just render a sprite on screen, I've made two component classes. The SpriteComponent and the MovementComponent. They don't contain any logic whatsoever only fields.

I would try to do something which actually needs an ECS, in your case you could just write 2 functions, try something like one sprite is static the other one moves(see next point), or they should behave differently, so you can actually use your components and systems.

The reason I called it "MovementComponent" is because I want it to signal that this entity can move from A to B, rather than PositionComponent which would indicate that it's stationary.

You could split those 2 up, your movementcomponent would hold a vector, your positioncomponent a point.

Anyway, a while ago I was at the same point, googling ECS gives lots of sites which introduce this "crazy new" system to do things, but only a few go into detail, i guess that's just something you have to learn by trying what works best for you.

Edited by BloodyEpi

Share on other sites

Since there is nothing like an ECS Pattern, your approach is neither right nor wrong, but a few things:

I dont think you need different Managers for different Componentpools, first of all you don't want to write one for every new component and second I cant think of anything they would handle in different ways, in C++ I used a templateclass for the componentpool, so every pool can be used like Pool<ComponentType>, I believe there's something similar in C#

[...]

Anyway, a while ago I was at the same point, googling ECS gives lots of sites which introduce this "crazy new" system to do things, but only a few go into detail, i guess that's just something you have to learn by trying what works best for you.

Did you read the first post I linked in the top and how that went?

I would like to make an engine so I split it into smaller bits and work on it one bit at a time using the Data Driven Design methodology.

My approach is inspired by how the creator of...I think Dungeon Siege? Made his game and explained in great detail some of the thoughts and considerations that went through the design process. Was also inspired by a few other articles to allow very minimal form of OOP.

Trimmed unnecessary quote text.

Share on other sites

Hi, I still think you are over thinking/overcomplicating things.

What Josh Petrie advised on the other post was to try and finish a small complete game/s without worrying so much on the data driven design and ECS. Just concentrate on making the game. Like having a main menu, gameplay, sound, input and rendering. eg Pong,

After you have done this very small game, you would have learned a lot. Plus it would feel really great to finish something. My advice set a deadline of 48 hours to make it.

As the game is done it will have

- some way to render 2D sprites

- some way to play sound

- some way to hold entity information

- collision detection code

Hopefully the time constraint will help to make a game rather than thinking about class design. The code will be quite "ugly/hacked in/not very reusable/" in general. The entities would be defined in code and may have their own update and draw/play sound functions..Probably during development, ideas would have emerged like why not store the entity template in a file or use a component entity system to make things more reusable? Write these thoughts on paper to remember for the next projects.

As you start your second (again small project), some parts could/should be done better given the previous learning experience.

Eg. Maybe this time, it would be better to let the user set the game window's width/height, and sound from a file.

Also it could be a good idea to store entity information for each game state in a file so that its easier to play around/experiment during development.

For example something like MainMenu.txt: (can be XML or JSON)

//entity type       //X and Y positions

buttonplay         100 100

buttonoptions    100 200

buttonexit           100 300

levelone.txt:

enemy           100, 200

boss              800, 300

You would then have a factory system which will read the information from the files and generate the right entities. The game just became even more data driven :)

On the next project, you can take a step further and have the entity template information stored in files rather than hard coded.

And so on until things become even more generic. As you start 3/4th project, probably you would be able to re-use quite alot of your previous code.

Slowly you will build up a robust re-usable set of libraries to draw entities, manage them, play sound, have physics <<< ie you have a game engine

Additionally, making a bit larger games will become easier as you already have the tools/experience needed.

You are on your way to make ever better data driven engine with games to prove that its functional.

Probably you would also be thinking how to implement an entity component system (which you already trying to design hehe)

Like BloodyEpi said, there is no set pattern for Entity Component Systems. There are so many implementations and ways of doing it.... Generally there seems to be two thoughts:

1 - Components just hold data and have systems which operate on them.

2 - Components hold their own logic. Systems may store the components/call their functions.

End result is king here. If it works, it works. Nobody will really care when they play the game so don’t worry if its not the best thing in the world.

Implement it and see if it works. If it doesn’t try to improve it.

In DDD you want to update things in pairs rather than in sequence. So instead of doing ABC, ABC, ABC which will have a horrible impact on performance, you do AAA, BBB, CCC and so on.

By updating systems by type  (AAA..., BBB....., CCC.....) its possible to use parallelism and improve performance. Eg Physics System divides 2000 components in 5 threads. Each thread updates 400 components. Overall taking less time. Also its cache friendly (should be faster).

Dungeon Siege? Made his game and explained in great detail some of the thoughts and considerations that went through the design process. Was also inspired by a few other articles to allow very minimal form of OOP.

What component systems allow is for minimal entity hierarchy by inheritance. Rather than using aggregation to develop entities, composition is used. This in turn keeps the entities more lean (as they have components which they need only) rather than extra blob which appears in deep inheritance hierarchy.

Overall the code base is easier to maintain, more reusable and adaptive to changes.

The system is build up of Entities which consist of Components, each defining a behaviour or attribute that the entity can have.

It may be better to split behaviour and attributes. By having some components with logic while others not, it can become confusing over time what should go where...

Think Single Responsibility Principle.

- Some systems will have no components. For example some of the systems which define the gameplay will just have some logic in them to check for game rules.

- How will you handle communication between components (if they have logic)  and systems?

- Also some components will need data from other components. How will they access it?

ECS are quite a complex beast to tackle hehe. Truthfully, the best way to get an idea if the system makes sense is to implement it. One great approach (imho) is to convert some small existing game/prototype from a hierarchy design to component based one.

(hope this is actually useful, off to work again hehe)

Share on other sites

Hi, I still think you are over thinking/overcomplicating things.

What Josh Petrie advised on the other post was to try and finish a small complete game/s without worrying so much on the data driven design and ECS. Just concentrate on making the game. Like having a main menu, gameplay, sound, input and rendering. eg Pong,

[...]

(hope this is actually useful, off to work again hehe)

All of that is useful yes.

I just...I don't know. It's kind of annoying the frak out of me that I have to do this kind of..guerilla warfare on DDD before I should be able to get it. Why not use the tools I got from the past and design something? (Mind you I've already made small applications with SFML to just render a sprite on screen, handle basic WASD movement (not pretty Lol) and such smaller things. I want to try and take it a step further :3) Just try and make small designs, try and implement, iterate and continue? I mean sure, when you learned a new language and such you did it by trial and error. But can't we learn/work smarter than that when we get something new to tackle?

It's all Logic after all. It must be logically possible to dechipher this pattern/philosophy/methodology one bit at a time until I got a certain whole :3

I will take in what you said though. Good ideas for a newb like me ^^

Trimmed unnecessary quote text.

Share on other sites

My interpretation of the downvotes is twofold. One, you're biting off more than you can chew. All of these acronyms: OOP, ECS, DDD take experience. Which means you should have a few years of actual software design and architecture under your belt before undertaking the newer paradigms. Two, another thing is that with software development is you learn more by doing, not just reading. Unfortunately, it seems you're wanting to do the opposite.

Share on other sites

It looks like you are over-engineering a solution for a problem you don't really understand.

The process is not as complex as you make it out to be.

You open a file. If there is data you read in the object. Read in a header.  The header gives you an object ID and a size of the data.  You pass that to a factory method, which in turn passes the data to sub-classes as needed.  The result is a game object. Init the object, place it in the world, and continue to the next object.

Creating the factory method is just looking up the right constructor that accepts a block of memory or a file stream, and calling it.

Keep it simple.  Start with the simplest thing that works. After you discover flaws in the system or useful additions, slowly expand it as your system needs.

Share on other sites

My interpretation of the downvotes is twofold. One, you're biting off more than you can chew. All of these acronyms: OOP, ECS, DDD take experience. Which means you should have a few years of actual software design and architecture under your belt before undertaking the newer paradigms. Two, another thing is that with software development is you learn more by doing, not just reading. Unfortunately, it seems you're wanting to do the opposite.

I have already been programming for 2 or 3 years. Mainly in Java. Learned C# and have been using it for about a years time. I am a computer science student and finish my profession bachelor in January. I am not trying to use the expressions losely :/

All of the programming I've done though followed OOP and OOD. Hence I try to learn something different.

And yes you learn by doing. But with everything you do you'd most likely want to make less mistakes and get more actual results, right? Yes, you learn from making mistakes. But making less mistakes in favour of better results is beneficial right? That's at least why I read up on how to program in the first place so that I could understand what I was doing and then I also had an easier time solving my problems.

It would just be nice if those who downvote would tell me why they did so, so that I could take in their feedback and hopefully learn from it. I came here to learn. Downvoting me for "biting off more than you can chew" is quite silly.

It looks like you are over-engineering a solution for a problem you don't really understand.

The process is not as complex as you make it out to be.

You open a file. If there is data you read in the object. Read in a header.  The header gives you an object ID and a size of the data.  You pass that to a factory method, which in turn passes the data to sub-classes as needed.  The result is a game object. Init the object, place it in the world, and continue to the next object.

Creating the factory method is just looking up the right constructor that accepts a block of memory or a file stream, and calling it.

Keep it simple.  Start with the simplest thing that works. After you discover flaws in the system or useful additions, slowly expand it as your system needs.

I can understand this way of developing and that is also what I aim to do (Currently). I just can't really get my head around the actual implementation in code. That's all.

Edited by vipar

Share on other sites
Sounds pretty simple to me... not sure why you're going to all the effort to significantly complicate it.

    public static class WidgetFactory
{
private static Dictionary<WidgetType, Func<WidgetType, Stream, Widget>> widgetCreator = new Dictionary<WidgetType, Func<WidgetType, Stream, Widget>>();

public static void AddWidgetType(WidgetType widgetType, Func<WidgetType, Stream, Widget> creator)
{
}

public static Widget CreateWidgetFromType(WidgetType widgetType, Stream data) {
return widgetCreator[widgetType](widgetType, data);
}
}

Edited by Washu

• 13
• 18
• 29
• 11