benmoran56 / esper

An ECS (Entity Component System) for Python
MIT License
537 stars 67 forks source link

Relationships #79

Closed Ziboo closed 1 year ago

Ziboo commented 1 year ago

Hello,

Do you have any best practices to create relationships between entities ?

For instance I have a Farm component and a Plant Component

Not sure what would be the best things to do...

A list of Plants or Entity Ids on the Farm class ?

Thanks a lot !

benmoran56 commented 1 year ago

Hi @Ziboo,

Generally speaking, entities shouldn't directly relate to each other directly. One specific entity shouldn't be tagged directly to any other specific entity.

If you have a case where all the type A entities need to interact with all the type B entities, you can usually push this logic up to the Processor.

You can also use single Components to "tag" entities.

What is the type of behavior that you're trying to accomplish?

Ziboo commented 1 year ago

Hi

I need to be able to link a Plants to a specific Farm. I can have multiple Farms.

I think the simplest example where relationship are useful is Inventory for instance. A game can have multiple Inventories and Items should be linked in some way to an Inventory

Right now for my exemple above I'm storing the Farm entity id on the plant component for filtering later but it's not ideal

@dataclass
class Plant:
    farm : int = -1
    growth: float = 0
    max_growth: float = 300

@dataclass
class Farm:
    pass

# somewhere in the code, need to filters Plants to a selected Farm

...
for entity, (plant, water) in game.GAME.ecs.get_components(Plant, WaterContainer):
            if plant.farm != self.selected_farm_entity:
                continue
 ....   
gretkierewicz commented 1 year ago

As I understand it, Farm should be entity here, not the Component. The question is, why do you want it to be Component in the first place.

Regardless, I have similar question, so will just post it here as another example. I'm creating roguelike as fun-side-project using this package.

Is making Target Component owning entity as attribute fine? This seems to violate a bit what was written here, about making pure Components. @benmoran56

gretkierewicz commented 1 year ago

Probably I've found some answers here: https://ajmmertens.medium.com/building-games-in-ecs-with-entity-relationships-657275ba2c6c

benmoran56 commented 1 year ago

@gretkierewicz Sorry I missed your messages. I only briefly looked at that blog post, but I do use the concept of a Target component myself sometimes.

gretkierewicz commented 1 year ago

Yeah I'm using that for now too, but I think when my project will grow I'll implement relationship feature anyway. If so, I'll create pull request with it as well

benmoran56 commented 1 year ago

Closing this for now, as there isn't really a single recomended method. However, using a "Target" style of Component seems reasonable enough.

Felecarpp commented 1 year ago

I made some tests using a str instead of type(component) as a key for get_components in World. I can format str before get_component to have the target in the key. For example, I use f"OwnedBy{player}" component key, player is an entity, so I can get all items holded by a player with get_components easily. Owever, I lost the typing of get_components.