{"id":13565983,"url":"https://github.com/ikvk/ecs_pattern","last_synced_at":"2025-04-08T04:17:14.904Z","repository":{"id":57837844,"uuid":"528307828","full_name":"ikvk/ecs_pattern","owner":"ikvk","description":"ECS pattern (Entity Component System) for creating games on python","archived":false,"fork":false,"pushed_at":"2025-01-23T13:18:58.000Z","size":28558,"stargazers_count":42,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-24T07:57:00.486Z","etag":null,"topics":["architecture","data-oriented-design","ecs","gamedev","games","pattern","python","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ikvk.png","metadata":{"files":{"readme":"README.rst","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":"2022-08-24T07:12:55.000Z","updated_at":"2025-02-13T14:38:24.000Z","dependencies_parsed_at":"2024-01-07T17:10:02.595Z","dependency_job_id":"f40b9ef5-7d54-4d24-94fa-bc1e4840b53f","html_url":"https://github.com/ikvk/ecs_pattern","commit_stats":{"total_commits":26,"total_committers":2,"mean_commits":13.0,"dds":0.07692307692307687,"last_synced_commit":"2b73bf085976794e2fd926a4e91159783402d235"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikvk%2Fecs_pattern","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikvk%2Fecs_pattern/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikvk%2Fecs_pattern/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikvk%2Fecs_pattern/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ikvk","download_url":"https://codeload.github.com/ikvk/ecs_pattern/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247773721,"owners_count":20993639,"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":["architecture","data-oriented-design","ecs","gamedev","games","pattern","python","python3"],"created_at":"2024-08-01T13:01:59.446Z","updated_at":"2025-04-08T04:17:14.865Z","avatar_url":"https://github.com/ikvk.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":".. http://docutils.sourceforge.net/docs/user/rst/quickref.html\n\n========================================================================================================================\necs_pattern 🚀\n========================================================================================================================\n\nImplementation of the ECS pattern (Entity Component System) for creating games.\n\nMake a game instead of architecture for a game.\n\n`Документация на Русском \u003chttps://github.com/ikvk/ecs_pattern/blob/master/_docs/README_RUS.rst#ecs_pattern-\u003e`_.\n\n.. image:: https://img.shields.io/pypi/dm/ecs_pattern.svg?style=social\n\n===============  ====================================================================================\nPython version   3.3+\nLicense          Apache-2.0\nPyPI             https://pypi.python.org/pypi/ecs_pattern/\nDependencies     dataclasses before 3.7, typing before 3.5\nRepo mirror      https://gitflic.ru/project/ikvk/ecs-pattern\n===============  ====================================================================================\n\n.. contents::\n\nIntro\n========================================================================================================================\n| ECS - Entity-Component-System - it is an architectural pattern created for game development.\n\nIt is great for describing a dynamic virtual world.\n\nBasic principles of ECS:\n\n* Composition over inheritance\n* Data separated from logic (Data Oriented Design)\n\n| *Component* - Property with object data\n| *Entity* - Container for properties\n| *System* - Data processing logic\n| *EntityManager* - Entity database\n| *SystemManager* - Container for systems\n\nInstallation\n========================================================================================================================\n::\n\n    $ pip install ecs-pattern\n\nGuide\n========================================================================================================================\n\nThe library provides you with 5 tools:\n\n.. code-block:: python\n\n    from ecs_pattern import component, entity, EntityManager, System, SystemManager\n\n* Describe components - component\n* Describe entities based on components - entity\n* Distribute the responsibility of processing entities by systems - System\n* Store entities in entity manager - EntityManager\n* Manage your systems with SystemManager\n\nComponent\n------------------------------------------------------------------------------------------------------------------------\n    | Property with object data. Contains only data, no logic.\n\n    | Use the ecs_pattern.component decorator to create components.\n\n    | Technically this is python dataclass.\n\n    | Use components as mixins for entities.\n\n    .. code-block:: python\n\n        @component\n        class ComPosition:\n            x: int = 0\n            y: int = 0\n\n        @component\n        class ComPerson:\n            name: str\n            health: int\n\nEntity\n------------------------------------------------------------------------------------------------------------------------\n    | Container for properties. Consists of components only.\n\n    | It is forbidden to add attributes to an entity dynamically.\n\n    | Use the ecs_pattern.entity decorator to create entities.\n\n    | Technically this is python dataclass with slots=True.\n\n    | Use EntityManager to store entities.\n\n    .. code-block:: python\n\n        @entity\n        class Player(ComPosition, ComPerson):\n            pass\n\n        @entity\n        class Ball(ComPosition):\n            pass\n\nSystem\n------------------------------------------------------------------------------------------------------------------------\n    | Entity processing logic.\n\n    | Does not contain data about entities and components.\n\n    | Use the ecs_pattern.System abstract class to create concrete systems:\n\n    | *system.start* - Initialize the system. It is called once before the main system update cycle.\n\n    | *system.update* - Update the system status. Called in the main loop.\n\n    | *system.stop* - Stops the system. It is called once after the completion of the main loop.\n\n    | Use SystemManager to manage systems.\n\n    .. code-block:: python\n\n        class SysInit(System):\n            def __init__(self, entities: EntityManager):\n                self.entities = entities\n\n            def start(self):\n                self.entities.init(\n                    TeamScoredGoalEvent(Team.LEFT),\n                    Spark(spark_sprite(pygame.display.Info()), 0, 0, 0, 0)\n                )\n                self.entities.add(\n                    GameStateInfo(play=True, pause=False),\n                    WaitForBallMoveEvent(1000),\n                )\n\n        class SysGravitation(System):\n            def __init__(self, entities: EntityManager):\n                self.entities = entities\n\n            def update(self):\n                for entity_with_pos in self.entities.get_with_component(ComPosition):\n                    if entity_with_pos.y \u003e 0:\n                        entity_with_pos.y -= 1\n\nEntityManager\n------------------------------------------------------------------------------------------------------------------------\n    | Container for entities.\n\n    | Use class ecs_pattern.EntityManager for creating an entity manager.\n\n    | Time complexity of get_by_class and get_with_component - like a dict\n\n    | *entities.add* - Add entities.\n\n    | *entities.delete* - Delete entities.\n\n    | *entities.delete_buffer_add* - Save entities to the delete buffer to delete later.\n\n    | *entities.delete_buffer_purge* - Delete all entities in the deletion buffer and clear the buffer.\n\n    | *entities.init* - Let manager know about entities. KeyError are raising on access to unknown entities.\n\n    | *entities.get_by_class* - Get all entities of the specified classes. Respects the order of entities.\n\n    | *entities.get_with_component* - Get all entities with the specified components.\n\n    .. code-block:: python\n\n        entities = EntityManager()\n        entities.add(\n            Player('Ivan', 20, 1, 2),\n            Player('Vladimir', 30, 3, 4),\n            Ball(0, 7)\n        )\n        for entity_with_pos in entities.get_with_component(ComPosition):\n            print(entity_with_pos.x, entity_with_pos.y)\n        for player_entity in entities.get_by_class(Player):\n            print(player_entity.name)\n            entities.delete_buffer_add(player_entity)\n        entities.delete_buffer_purge()\n        entities.delete(*tuple(entities.get_by_class(Ball)))  # one line del\n\nSystemManager\n------------------------------------------------------------------------------------------------------------------------\n    | Container for systems.\n\n    | Works with systems in a given order.\n\n    | Use the ecs_pattern.SystemManager class to manage systems.\n\n    | *system_manager.start_systems* - Initialize systems. Call once before the main systems update cycle.\n\n    | *system_manager.update_systems* - Update systems status. Call in the main loop.\n\n    | *system_manager.stop_systems* - Stop systems. Call once after the main loop completes.\n\n    .. code-block:: python\n\n        entities = EntityManager()\n        entities.add(\n            Player('Ivan', 20, 1, 2),\n            Player('Vladimir', 30, 3, 4),\n            Ball(0, 7)\n        )\n        system_manager = SystemManager([\n            SysPersonHealthRegeneration(entities),\n            SysGravitation(entities)\n        ])\n        system_manager.start_systems()\n        while play:\n            system_manager.update_systems()\n            clock.tick(24)  # *pygame clock\n        system_manager.stop_systems()\n\nExamples\n========================================================================================================================\n* `Pong \u003chttps://github.com/ikvk/ecs_pattern/tree/master/examples/pong#pong---classic-game\u003e`_: game - pygame + ecs_pattern\n* `Snow day \u003chttps://github.com/ikvk/ecs_pattern/tree/master/examples/snow_day#snow-day---scene\u003e`_: scene - pygame + ecs_pattern\n* `Trig fall \u003chttps://github.com/ikvk/ecs_pattern/tree/master/examples/trig#trig-fall---game\u003e`_: commercial game - pygame + ecs_pattern + numpy\n\nAdvantages\n========================================================================================================================\n* Memory efficient - Component and Entity use dataclass\n* Convenient search for objects - by entity class and by entity components\n* Flexibility - loose coupling in the code allows you to quickly expand the project\n* Modularity - the code is easy to test, analyze performance, and reuse\n* Execution control - systems work strictly one after another\n* Following the principles of the pattern helps to write quality code\n* Convenient to parallelize processing\n* Compact implementation\n\nDifficulties\n========================================================================================================================\n* It can take a lot of practice to learn how to cook ECS properly\n* Data is available from anywhere - hard to find errors\n\nNewbie mistakes\n========================================================================================================================\n* Inheritance of components, entities, systems\n* Ignoring the principles of ECS, such as storing data in the system\n* Raising ECS to the absolute, no one cancels the OOP\n* Adaptation of the existing project code under ECS \"as is\"\n* Use of recursive or reactive logic in systems\n* Using EntityManager.delete in get_by_class, get_with_component loops\n\nGood Practices\n========================================================================================================================\n* Use \"Singleton\" components with data and flags\n* Minimize component change locations\n* Do not create methods in components and entities\n* Divide the project into scenes, a scene can be considered a cycle for the SystemManager with its EntityManager\n* Use packages to separate scenes\n\nProject tree example:\n::\n\n    /common_tools\n        __init__.py\n        resources.py\n        i18n.py\n        gui.py\n        consts.py\n        components.py\n        math.py\n    /menu_scene\n        __init__.py\n        entities.py\n        main_loop.py\n        surfaces.py\n        systems.py\n    /game_scene\n        __init__.py\n        entities.py\n        main_loop.py\n        surfaces.py\n        systems.py\n    main.py\n\nReleases\n========================================================================================================================\n\nHistory of important changes: `release_notes.rst \u003chttps://github.com/ikvk/ecs_pattern/blob/master/_docs/release_notes.rst\u003e`_\n\nHelp the project\n========================================================================================================================\n* Found a bug or have a suggestion - issue / merge request 🎯\n* There is nothing to help this project with - help another open project that you are using ✋\n* Nowhere to put the money - spend it on family, friends, loved ones or people around you 💰\n* Star the project ⭐\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fikvk%2Fecs_pattern","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fikvk%2Fecs_pattern","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fikvk%2Fecs_pattern/lists"}