Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce poor man's ECS #14

Merged
merged 8 commits into from
Sep 27, 2024
Merged

Introduce poor man's ECS #14

merged 8 commits into from
Sep 27, 2024

Conversation

jjyr
Copy link
Owner

@jjyr jjyr commented Sep 27, 2024

Introduce a little bit ECS to improve the composition.

The previous implementation used the EntType trait to define entity callbacks, but it encountered several limitations:

  • Accessing fields of EntType requires downcasting, which is cumbersome.
  • During callbacks, it's impossible to access the self EntType from the World, as the callback holds a reference to it.

It turns out, in Rust, our only choice is ECS. The traditional OOP approch always holds the reference, which prevent us from accessing entities in a unified method.

Of cause, this ECS is different with that ECS, we have so many ECS. The bevy ECS is the most popular and powerful implementation in the rust world, and it is very inspiring. But I found it's too complicated for me, the query and system schedule is powerful but it feel like overkilled to me. I have tried bevy ECS, and my experience tell me I want something simpler, no complex queries and just callback style code.

I came across a blog post, Archetypal ECS Considered Harmful, which inspired me. It reassured me that there are others who also seek a simpler ECS.

What I truly need is exactly what the post discusses - the compositional capabilities of ECS. Components are the key. By introducing components, we gain the ability to dynamically access data and provide a unified way to work with entities, solving the problems I faced.

Turning into ECS, I refactor the old EntType into EntHooks, a component, Any entity providing this component will be called by the engine. I also remove the Entity struct, moving its fields into seperate components: Transform, Phisics, Sprite.

Some system, such as collision detection, need state, so I borrowed the idea of Resource from bevy. I added a CollisionSet resource, entities can be added into CollisionSet to enable the collision detection.

Here’s an example of accessing an entity's component:

// Get mutable ent ref
let mut ent = w.get_mut(ent).unwrap();
// get mutable transform component ref
let transform = ent.get_mut::<Transform>().unwrap();

See Demo for a full example.

@jjyr jjyr merged commit 1b59dd9 into master Sep 27, 2024
10 checks passed
@jjyr jjyr deleted the ecs branch September 27, 2024 17:38
@jjyr jjyr restored the ecs branch January 1, 2025 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant