{"id":26558108,"url":"https://github.com/judelco/entitas-cpp","last_synced_at":"2025-03-31T11:06:52.269Z","repository":{"id":65263639,"uuid":"53688054","full_name":"JuDelCo/Entitas-Cpp","owner":"JuDelCo","description":"Entitas++ is a fast Entity Component System (ECS) C++11 port of Entitas C#","archived":false,"fork":false,"pushed_at":"2023-07-01T10:42:53.000Z","size":23,"stargazers_count":346,"open_issues_count":0,"forks_count":61,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-03-22T12:32:35.112Z","etag":null,"topics":["cpp","design-pattern","ecs","entitas","entity","entity-component","entity-component-system","entity-framework","game","game-development","game-engine","gamedev","performance"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JuDelCo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-03-11T18:27:30.000Z","updated_at":"2025-02-20T08:59:04.000Z","dependencies_parsed_at":"2025-03-22T12:41:02.262Z","dependency_job_id":null,"html_url":"https://github.com/JuDelCo/Entitas-Cpp","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuDelCo%2FEntitas-Cpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuDelCo%2FEntitas-Cpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuDelCo%2FEntitas-Cpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuDelCo%2FEntitas-Cpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JuDelCo","download_url":"https://codeload.github.com/JuDelCo/Entitas-Cpp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246457970,"owners_count":20780676,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","design-pattern","ecs","entitas","entity","entity-component","entity-component-system","entity-framework","game","game-development","game-engine","gamedev","performance"],"created_at":"2025-03-22T12:30:39.062Z","updated_at":"2025-03-31T11:06:52.237Z","avatar_url":"https://github.com/JuDelCo.png","language":"C++","readme":"Entitas++\n=====================\n\nEntitas++ is a fast Entity Component System Framework (ECS) C++11 port of [Entitas v0.29.0 for C# and Unity](https://github.com/sschmid/Entitas-CSharp/tree/0.29.0).\n\nThere are some differences between both, so please check the code and notes below !\n\nAny feedback is welcome !\n\nDocumentation\n=====================\n\n#### Overview\n\nAs in Entitas C#, basic code architecture is the same:\n\n```\n+------------------+\n|       Pool       |\n|------------------|\n|    e       e     |      +-----------+\n|        e     e---|----\u003e |  Entity   |\n|  e        e      |      |-----------|\n|     e  e       e |      | Component |\n| e            e   |      |           |      +-----------+\n|    e     e       |      | Component-|----\u003e | Component |\n|  e    e     e    |      |           |      |-----------|\n|    e      e    e |      | Component |      |   Data    |\n+------------------+      +-----------+      +-----------+\n  |\n  |\n  |     +-------------+  Groups:\n  |     |      e      |  Subsets of entities in the pool\n  |     |   e     e   |  for blazing fast querying\n  +---\u003e |        +------------+\n        |     e  |    |       |\n        |  e     | e  |  e    |\n        +--------|----+    e  |\n                 |     e      |\n                 |  e     e   |\n                 +------------+\n```\n\n#### Creating a new component example\n\n###### Entitas C\u0026#35;\n```csharp\npublic class PositionComponent : IComponent {\n    public float x;\n    public float y;\n    public float z;\n}\n\n//...\n\nvar pool = new Pool(ComponentIds.TotalComponents);\nvar e = pool.CreateEntity();\n\ne.AddPosition(1f, 2f, 3f);\ne.ReplacePosition(3f, 2f, 1f);\ne.RemovePosition();\n\nvar posX = e.position.x;\nvar hasPosition = e.hasPosition;\n```\n\n###### Entitas++\n```cpp\n// I suggest you to use structs instead, they are the same and all members/methods are public by default.\nclass Position : public IComponent {\n    public:\n        // You must provide at least ONE public \"Reset\" method with any parameters you want\n        void Reset(float px, float py, float pz) {\n            x = px;\n            y = py;\n            z = pz;\n        }\n\n        float x;\n        float y;\n        float z;\n};\n\n//...\n\nauto pool = new Pool();\nauto e = pool-\u003eCreateEntity();\n\ne-\u003eAdd\u003cPosition\u003e(1f, 2f, 3f);\ne-\u003eReplace\u003cPosition\u003e(3f, 2f, 1f);\ne-\u003eRemove\u003cPosition\u003e();\n\nfloat posX = e-\u003eGet\u003cPosition\u003e()-\u003ex;\nbool hasPosition = e-\u003eHas\u003cPosition\u003e();\n```\n\n#### Basic component management\n\n###### Entitas C\u0026#35;\n```csharp\nentity.AddPosition(3, 7);\nentity.AddHealth(100);\nentity.isMovable = true;\n\nentity.ReplacePosition(10, 100);\nentity.ReplaceHealth(entity.health.value - 1);\nentity.isMovable = false;\n\nentity.RemovePosition();\n\nvar hasPos = entity.hasPosition;\nvar movable = entity.isMovable;\n```\n\n###### Entitas++\n```cpp\nentity-\u003eAdd\u003cPosition\u003e(3, 7);\nentity-\u003eAdd\u003cHealth\u003e(100);\nentity-\u003eReplace\u003cMovable\u003e(); // There is no helper in here, you must use \"Replace\" and \"Remove\" methods\n\nentity-\u003eReplace\u003cPosition\u003e(10, 100);\nentity-\u003eReplace\u003cHealth\u003e(entity-\u003eGet\u003cHealth\u003e()-\u003evalue - 1);\nentity-\u003eRemove\u003cMovable\u003e();\n\nentity-\u003eRemove\u003cPosition\u003e();\n\nbool hasPos = entity-\u003eHas\u003cPosition\u003e();\nbool movable = entity-\u003eHas\u003cMovable\u003e(); // Again, you must use \"Has\" to check if an entity has a component\n```\n\n#### Pools\n\n###### Entitas C\u0026#35;\n```csharp\n// Pools.pool is kindly generated for you by the code generator\nvar pool = Pools.pool;\nvar entity = pool.CreateEntity();\nentity.isMovable = true;\n\n// Returns all entities having MovableComponent and PositionComponent.\n// Matchers are also generated for you.\nvar entities = pool.GetEntities(Matcher.AllOf(Matcher.Movable, Matcher.Position));\nforeach (var e in entities) {\n    // do something\n}\n```\n\n###### Entitas++\n```cpp\n// No code generator == no \"Pools\". You must handle yourself your Pools !\nauto pool = new Pool();\nauto entity = pool-\u003eCreateEntity();\nentity-\u003eReplace\u003cMovable\u003e(); // I used \"Replace\" but in this case is better to use \"Add\" directly\n\n// Returns all entities having MovableComponent and PositionComponent.\n// Matchers are also generated for you.\nauto entities = pool-\u003eGetEntities(Matcher_AllOf(Movable, Position)); // *Some magic preprocessor involved*\nfor (auto \u0026e : entities) { // e is a shared_ptr of Entity\n    // do something\n}\n```\n\n#### Group events\n\n###### Entitas C\u0026#35;\n```csharp\npool.GetGroup(Matcher.Position).OnEntityAdded += (group, entity, index, component) =\u003e {\n    // Do something\n};\n```\n\n###### Entitas++\n```cpp\npool-\u003eGetGroup(Matcher_AllOf(Position))-\u003eOnEntityAdded += [](std::shared_ptr\u003cGroup\u003e group, EntityPtr entity, ComponentId index, IComponent* component) {\n    // Do something\n};\n```\n\n#### Group Observer\n\n###### Entitas C\u0026#35;\n```csharp\nvar group = pool.GetGroup(Matcher.Position);\nvar observer = group.CreateObserver(GroupEventType.OnEntityAdded);\nforeach (var e in observer.collectedEntities) {\n    // do something\n}\nobserver.ClearCollectedEntities();\n```\n\n###### Entitas++\n```cpp\nauto group = pool-\u003eGetGroup(Matcher_AllOf(Position)); // There are _AnyOf and _NoneOf too !\nauto observer = group-\u003eCreateObserver(GroupEventType::OnEntityAdded);\nfor (auto \u0026e : observer-\u003eGetCollectedEntities()) {\n    // do something\n}\nobserver-\u003eClearCollectedEntities();\n```\n\n#### Execute Systems\n\n###### Entitas C\u0026#35;\n```csharp\npublic class MoveSystem : IExecuteSystem, ISetPool {\n    Group _group;\n\n    public void SetPool(Pool pool) {\n        _group = pool.GetGroup(Matcher.AllOf(Matcher.Move, Matcher.Position));\n    }\n\n    public void Execute() {\n        foreach (var e in _group.GetEntities()) {\n            var move = e.move;\n            var pos = e.position;\n            e.ReplacePosition(pos.x, pos.y + move.speed, pos.z);\n        }\n    }\n}\n```\n\n###### Entitas++\n```cpp\nclass MoveSystem : public IExecuteSystem, public ISetPool {\n    std::weak_ptr\u003cGroup\u003e _group;\n\n    public:\n        void SetPool(Pool* pool) {\n            _group = pool-\u003eGetGroup(Matcher_AllOf(Move, Position));\n        }\n\n        void Execute() {\n            for (auto \u0026e : _group.lock()-\u003eGetEntities()) {\n                auto move = e-\u003eGet\u003cMove\u003e();\n                auto pos = e-\u003eGet\u003cPosition\u003e();\n                e-\u003eReplace\u003cPosition\u003e(pos-\u003ex, pos-\u003ey + move-\u003espeed, pos-\u003ez);\n            }\n        }\n};\n```\n\n#### Reactive Systems\n\n###### Entitas C\u0026#35;\n```csharp\npublic class RenderPositionSystem : IReactiveSystem {\n    public TriggerOnEvent trigger { get { return Matcher.AllOf(Matcher.Position, Matcher.View).OnEntityAdded(); } }\n\n    public void Execute(List\u003cEntity\u003e entities) {\n        // Gets executed only if the observed group changed.\n        // Changed entities are passed as an argument\n        foreach (var e in entities) {\n            var pos = e.position;\n            e.view.gameObject.transform.position = new Vector3(pos.x, pos.y, pos.z);\n        }\n    }\n}\n```\n\n###### Entitas++\n```cpp\nclass RenderPositionSystem : public IReactiveSystem {\n    public:\n        RenderPositionSystem() {\n        \ttrigger = Matcher_AllOf(Position, View).OnEntityAdded();\n        }\n\n        void Execute(std::vector\u003cEntityPtr\u003e entities) {\n            // Gets executed only if the observed group changed.\n            // Changed entities are passed as an argument\n            for (auto \u0026e : entities) {\n                auto pos = e-\u003eGet\u003cPosition\u003e();\n                // NOTE: Unity-only example, but this maybe could be the code if Unity were compatible with C++\n                e-\u003eGet\u003cView\u003e()-\u003egameObject.transform.position = new Vector3(pos-\u003ex, pos-\u003ey, pos-\u003ez);\n            }\n        }\n}\n```\n\nNotes\n=====================\n\n- All code above was written using: ```using namespace EntitasPP;```, if you don't, you must prepend all the classes with the namespace ```EntitasPP::```.\n- There is *no* code generator because C++ lacks of [code reflection](https://en.wikipedia.org/wiki/Reflection_(computer_programming)). So all code must be done by you, but there are a lot of templating involved in here to ease the work for you anyways (see code above).\n- ['Systems' class](https://github.com/sschmid/Entitas-CSharp/blob/94ab9b172987a65a7facfd4c383b621a4cbb0bca/Entitas/Entitas/Systems.cs#L8) was renamed to 'SystemContainer'. You can see a simple example of use in the provided 'main.cpp'.\n- All 'ToString()' methods were removed. If you need to track identifiers between entities I suggest you to use your own custom Component.\n- AERC (Automatic Entity Reference Counting) was implemented using smart pointers. (Yeah! Take that C# :stuck_out_tongue_winking_eye:)\n\nIf you need more documentation of the architecture of the framework, please go to [Entitas v0.29.0 C# Wiki](https://github.com/sschmid/Entitas-CSharp/wiki/Home/18f70d987d94be972c179bbd71b3a175263c0f04) since this framework has a lot on common with the original C# one.\n\nThe MIT License (MIT)\n=====================\n\nCopyright © 2020 Juan Delgado (JuDelCo)\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the “Software”), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjudelco%2Fentitas-cpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjudelco%2Fentitas-cpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjudelco%2Fentitas-cpp/lists"}