An open source C++ entity system.

Related tags

Miscellaneous anax
Overview

anax Build Status

ARCHIVED: as I haven't maintained this library for at least a couple of years. I don't have the time or interest to work on this. Please use another library or just write your game without an ECS ;)

anax is an open source C++ entity system designed to be portable, lightweight and easy to use. It is aimed toward Game Development, however it would be possible to use it for other projects.

What's an Entity System?

An entity system, or entity component system is a pattern for building complex extensible projects (typically games). It separates functionality into three major parts: components, systems and entities. Where entities are used to describe an object within the game, components are used to store data for the entities to describe them, and systems are used to contain game logic.

You can read about them further here.

Getting Started

Dependencies

To compile, install, and use anax, a C++11 compliant compiler is required.

Installation

(mkdir -p build && cmake .. && make install)

A more detailed tutorial on how to install is available on the wiki.

Quick Tutorial

This section will explain how to use the library, but it will not go into much specific detail. If you want a more detailed guide, please refer to this page on the wiki.

NOTE:

It is assumed you know what an Entity System is.

The World

A World is used to describe you game world or 'entity system' if you will. You must always have at least one World object in order to use anax. e.g.

World world;

Entities

An entity is what you use to describe an object in your game. e.g. a player, a gun, etc. To create entities, you must have a World object, and call createEntity() on the World object.

World world;
// ... 
Entity entity = world.createEntity();

Entities are implemented as an identifier (32 or 64 bits). The Entity objects have a reference to the World object, and may be accessed via getWorld(). The Entity class acts as a handle to entities, you can think of it as a pointer. You may have multiple Entity handles to represent the same entity, e.g.

Entity entity1 = world.createEntity();
Entity entity2 = entity1; // entity2 and entity1 "point" to the same entity

To destroy/kill an entity, you can either call World::killEntity or Entity::kill. e.g.

entity.kill();
// or
world.killEntity(entity);

Once you have killed an entity, other copies of your entity handles will automatically be invalidated and will not be of use (an assertion will occur if you attempt to use an invalidated entity). e.g.

Entity entity1 = world.createEntity();
Entity entity2 = entity1;

entity1.kill();

// This will cause an assertion
// see below for details about this member function
entity2.addComponent<Position>(0, 3, 5);

Components

A Component is used to describe data for an Entity, for example: the position, velocity, etc. To define your own component, you simply inherit from Component.

struct PositionComponent : anax::Component
{
	// ...
};

You may add/remove/get components to entities through the public methods defined in the entity class.

  • addComponent
  • removeComponent
  • getComponent

e.g.

// adding components
entity.addComponent<PositionComponent>(2, 3, 5);

// removing components
entity.removeComponent<PositionComponent>();

// getting components
auto pos = entity.getComponent<PositionComponent>();

Systems

A System is used to contain on entities with specific components (require or exclude a set of component types). It is typically used to update, render or perform some logic these entities.

struct MovementSystem : anax::System<anax::Requires<PositionComponent, VelocityComponent>, anax::Excludes<ParalizedComponent>>
{
	// ...
};

That is, a movement system requires entities with a PositionComponent and VelocityComponent, also excludes entities with a ParalizedComponent. You may determine if an entity is removed/added to the system via these two override-able (virtual) methods:

  • onEntityAdded(Entity&)
  • onEntityRemoved(Entity&)

That's basically it, you can pretty much go and code. If you want more details, check the documentation or this getting started guide on the wiki.

Get Involved

Want to get involved with the project? You are free to help out on the project, but please see the CONTRIBUTING.md file before doing so.

Also, don't be afraid to send pull requests, especially for those that fix bugs ([email] me if you're unsure)!

License

See LICENSE.

[Entity Systems]:http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/) [Artemis]: http://gamadu.com/artemis/ [boost]: http://boost.org/ [email]: mailto:[email protected]

Comments
  • Addition: WorldStateMachine?

    Addition: WorldStateMachine?

    So I'm working on a game with Anax. I'm using finite state machines to model the change in game state (i.e. main menu vs. in-game vs. splash screen, etc.). I don't wanna publish the source code yet, because it's not properly tested or polished, but here's the gist of it;

    • The WorldStateMachine, of course, maintains a pointer to the World in question (just a raw pointer, though).
    • Rather than directly passing in a new state (e.g. wsm.changeState(TITLE_SCREEN)), I'm writing it with more traditional transitions in mind (e.g. wsm.transition(EXIT)). The states are nouns of some kind (title screen, in-game, etc.), and the transitions are verbs (exit, advance, pause, etc.). Whenever you transition, the WorldStateMachine takes the input and the current state, and looks at the transition table (a std::map) to decide where to go next. If no transition is defined, an exception is thrown.
    • The WorldState itself consists of just three function objects; one called on state exit, one called on state entry, and one called every frame.
    • Systems are not explicitly added to WorldStates; that's what onEnter() is for (though that could be up for debate)
    • WorldState favors composition over inheritance (you're not subclassing it, you're passing functions into it), though I don't see why I couldn't allow both with abstract base classes or something.
    • All states in a WorldStateMachine are referenced by some key
    • There are three template parameters for WorldStateMachine; one is the state type (which is ideally an enum), another is transition type (also an enum, preferably), the third is a parameter pack of arbitrary arguments (e.g. a std::vector<sf::Event>; I know you use SFML). For a WorldStateMachine to be compatible with a WorldState, it must share the last parameter type.
      • This part of the design I'm a bit iffy about. Subject to change.

    I'm writing this for my game, but if I were to polish it up and write unit tests, would you want it in Anax?

    enhancement suggestion 
    opened by JesseTG 9
  • Removing Component causes crash

    Removing Component causes crash

    Calling entity.removeComponent(), when any System uses that Component causes crash and/or 'onEntityRemoved' does NOT get called. However, outright killing the Entity does trigger the onEntityRemoved System callback.

    Error: "Assertion failed: entity.isValid() && hasComponent(entity, componentTypeId) && "Entity is not valid or does not contain component", file C:\anax\detail\EntityComponentStorage.cpp, line 75"

    bug 
    opened by jabza 8
  • How is this library different from EntityX, what are the use cases where it is preferable?

    How is this library different from EntityX, what are the use cases where it is preferable?

    I'm looking for a Component-Entity-System library, and I found these two. The faq lists EntityX as an inspiration. I find the two very similar in goals and implementation as well. Is there a killer advantage to choose either?

    question discussion 
    opened by sztomi 6
  • License

    License

    Hi Miguel Martin, first I would like to say I'm impressed that you are building this kind of tools at your age, it usually take some years of coding to get the knowledge and confidence to code this things.

    My questions is about the licensing of the library. I'm building a simple game engine and I'm currently using Artemis-Cpp for the Entity-Component System, but your implementation catched my attention and I would like to give it a try and see how it performs (I'm more interested in code readability rather than raw performance TBH) but the copyright is holding me off at this point. My game engine will have a MIT license and I don't know if that conflicts with your copyright licensing.

    Will it be sufficient to include a Copyright note stating that I use anax, which is implemented and copyrighted by Miguel Martin?

    question 
    opened by L4D15 5
  • Same Entity added to System every time activate() is called.

    Same Entity added to System every time activate() is called.

    Just noticed this, I'm guessing it will just require some sort of 'hasEntity()' interface in the System class? This worked for me:

    // if the entity passes the filter the system has
    if(i.second->getComponentFilter().doesPassFilter(m_entityAttributes.componentStorage.getComponentTypeList(entity)))
    {
        if(!i.second->hasEntity(entity))
        {
            i.second->add(entity); // add it to the system
            detail::EnsureCapacity(attribute.systems, systemIndex); 
                            attribute.systems[systemIndex] = true;
        }
    }
    
    bug 
    opened by jabza 5
  • Various bug fixes

    Various bug fixes

    Fixed Entity::Id's being re-cycled incorrectly. Fixed issue where re-activating Entities caused them to be re-added to their Systems. Added the ability for an empty Entity handle to check its validity without asserting.

    bug enhancement 
    opened by jabza 4
  • Using multiple Worlds as spaces?

    Using multiple Worlds as spaces?

    I just read an interesting article on Tuts+ about spaces, which are analogous to layers on Photoshop or similar; a game object (an Entity, in Anax's case) occupies a space, and interacts only with other objects on that space. My question is this; do you think it's a good idea to use Worlds as spaces by having multiple Worlds exist at a time, each with their own Entitys, Components, and Systems? Or might that break something?

    question 
    opened by JesseTG 4
  • Can you save some markup? Anax seems very verbose

    Can you save some markup? Anax seems very verbose

    Sorry for writing it here, I think I am abusing the functionality of GitHub's issues again, but there is no forum or chat.

    In this example the systesm are first declared

    SpriteRenderingSystem m_spriteRenderingSystem;
    AnimationSystem m_animationSystem;
    MovementSystem m_movementSystem;
    PlayerInputSystem m_playerInputSystem;
    CollisionSystem m_collisionSystem;
    

    then added to the world

    m_world.addSystem(m_spriteRenderingSystem);
    m_world.addSystem(m_animationSystem);
    m_world.addSystem(m_playerInputSystem);
    m_world.addSystem(m_movementSystem);	
    m_world.addSystem(m_collisionSystem);
    

    and then their update method is called every frame

    m_collisionSystem.update(deltaTime);	
    m_animationSystem.update(deltaTime);
    m_playerInputSystem.update(deltaTime);
    m_movementSystem.update(deltaTime);
    

    And this is just from a simple example.

    I thought about having a container (like std::vector), which would cut down on the latter two snippets, which could be replaced with a for-loop, but the data types are different for all of them. I haven't worked with this yet, but maybe std::any or having them be pointers of a base type that all systems inherit from?

    What's your input?

    opened by kim366 3
  • Collision Tutorial 1st draft

    Collision Tutorial 1st draft

    Basic collision tutorial - I still need to clean it up, fix the member variable prefixes (i used mVar instead of m_Var XD), remove some debug lines, and document a little more. There's one problem that I can't figure out - for some reason, the sprites are getting rendered half of their width to the right; but their bounding boxes are at the correct position. If you don't see anything right away, don't worry about it - I'll probably be able to get down to the bottom of it within a couple of days.

    Anyway, tell me if you see anything glaringly wrong in the Game.cpp - I followed your convention layed out in the Movement tutorial, and made Game inherit from CollisionSystem::Listener and overrode the CollisionSystem::Listener function. In the original source, you didn't have the onCollisionOccured function an absolute virtual - I made it so; is there a reason you didn't?

    enhancement repo-structure 
    opened by johnmarinelli 3
  • Fixed -stdlib=libc++ error with g++ 4.8.1

    Fixed -stdlib=libc++ error with g++ 4.8.1

    When executing make if you are using g++ 4.8.1 you get the error "c++: error: unrecognized command line option ‘-stdlib=libc++’" This fixes that.

    bug enhancement 
    opened by benbot 3
  • Linker Errors VS2017. Not sure what's wrong?

    Linker Errors VS2017. Not sure what's wrong?

    LNK2019 unresolved external symbol "public: void __thiscall anax::World::SystemDeleter::operator()(class anax::detail::BaseSystem *)const " (??RSystemDeleter@World@anax@@QBEXPAVBaseSystem@detail@2@@Z) referenced in function "public: __thiscall std::unique_ptr<class anax::detail::BaseSystem,struct anax::World::SystemDeleter>::~unique_ptr<class anax::detail::BaseSystem,struct anax::World::SystemDeleter>(void)" (??1?$unique_ptr@VBaseSystem@detail@anax@@USystemDeleter@World@3@@std@@QAE@XZ)

    Getting this whenever using anax::World. I've used both Visual Studio and mingw32-make and get the same results. I get the DLL and put it in the .exe directory. I feel like there should be a .lib file but I don't get any?

    opened by Jasonfran 2
  • anax and box2d  entity from userdata error

    anax and box2d entity from userdata error

    Hi frend! I can not understand the error with the library box2d. If I get the entity of the userdata http://www.iforce2d.net/b2dtut/user-data You could help me? I already suffering a few days with this problem ._.

    #include <anax/anax.hpp>
    #include "Box2D/Box2D.h"
    #include "iostream"
    
    anax::World anax_world;
    b2World * b2world  = new b2World(b2Vec2 {0, 9.8});// standart physic init
    
    struct Player : anax::Component {
        Player() {}
    };
    struct Physic : anax::Component {
        Physic() {}
        b2Body * b2body;
    };
    struct TestSystem : anax::System<anax::Requires<Physic>>
    {
        void init()
        {
            auto entities = getEntities();
            for (auto entity : entities) {
    
                auto & b2body = entity.getComponent<Physic>().b2body;
                b2BodyDef bodyDef;
                bodyDef.position.Set(0,0);
                bodyDef.type = b2_dynamicBody;
                b2body = b2world->CreateBody(&bodyDef);
                b2PolygonShape shape;
                shape.SetAsBox(1,1);// create simple box for test
                b2body->SetUserData(&entity);// add this entity to userdata
                b2body->CreateFixture(&shape,1.0);
            }
        }
    
        void update()
        {
            auto entities = getEntities();
            for (auto entity : entities) {
    
                auto & b2body = entity.getComponent<Physic>().b2body;
                anax::Entity * entity_from_data =
                        (anax::Entity*)b2body->GetUserData();// get entity from userdata
    
                if(entity_from_data)// if != NULL
                if(entity_from_data->hasComponent<Player>())// FIXME here is error!!!
                    std::cout << "has Player"<< std::endl;
                else
                   std::cout << "no Player"<< std::endl;
            }
        }
    
    };
        int main()
        {
            TestSystem testSystem;
            // add system
            anax_world.addSystem(testSystem);
    
            // add entity
            anax::Entity player;
            player = anax_world.createEntity();
            player.addComponent<Physic>();
            player.addComponent<Player>();
            player.activate();
    
            // initialization
            anax_world.refresh();
            testSystem.init();
            int i;
            while (++i < 10)// Main  loop
            {
                anax_world.refresh(); // ECS update
                testSystem.update();
    
                b2world->Step(1.0f/30.0f, 6, 4);//physic update
            }
            // De-Initialization
            anax_world.clear();
            delete b2world;
            std::cout << "test end" << std::endl;
        }
    
    
    
    opened by dzanis 2
  • More pre/post condition asserts

    More pre/post condition asserts

    I had to add a lot of my own asserts to the various Id and entity add/remove functions before I finally determined I was killing entities multiple times before calling refresh and that this isn't valid. It is reasonable that it isn't valid, but not obvious enough to not even be asserted for I would argue (almost nothing that is possible to do incorrectly is)!

    Given that the kill commands are queued and then processed during refresh one might assume (as I did without even realising it) that duplicate kill operations would naturally be collapsed. Or that the container that contains the entities would be a unique set rather than a vector upon which multiple copies of the same entity could be pushed.

    Adding this in World::killEntity finally caught my error:

    ANAX_ASSERT(isValid(entity), "invalid entity tried to kill");
    ANAX_ASSERT(std::find(std::cbegin(m_entityCache.killed), std::cend(m_entityCache.killed), entity) == std::cend(m_entityCache.killed), "entity tried to kill multiple times");
    
    opened by billw2012 1
  • Shared library does not build both dll and .lib

    Shared library does not build both dll and .lib

    Hello, when testing the library today I have noticed that under Visual Studio 2015 when configuring with BUILD_SHARED_LIBS no lib is generated. This happens when the project does not have any kind of dllexport in the code.

    I use a cross-platform way to do exports in one of my projects (link). I am going to work on this in the following days and submit a PR. But I do not know which are the things that should be exported from this lib.

    opened by mattiascibien 0
  • Can't call activate() from within onEntityAdded.

    Can't call activate() from within onEntityAdded.

    Found this problem while wanting to remove a component of an entity, when that entity was added to a new system.

    Here's my understanding of the problem: a. |onEntityAdded| is called while iterating over |m_entityCache.activated|. b. Calling activate() leads to adding an entry to |m_entityCache.activated|. Unfortunately, iterating on a vector that you modify doesn't work.

    Possible fix: Copy (or swap pointers/std::move) all the arrays over which you iterate at the beginning of World::refresh(), clear them, and only then iterate over them:

    void World::refresh() {
      auto copyActivated = m_entityCache.activated;
      auto copyDeactivated = m_entityCache.deactivated;
      auto copyKilled = m_entityCache.killed;
      m_entityCache.clearTemp();
      for (auto& entity : copyActivated) {
    
    opened by jyaif 1
  • Creating Component with Entity::addComponent

    Creating Component with Entity::addComponent

    Hi Miguel, I noticed that you implemented creating Component with addComponent() and passing initializer list as arguments, but that doesn't work on my compiler as Component that I'm creating has BaseClass and I haven't seen you use it in any example. Is this just future feature? I read that this should be working on C++17 compilers.

    example: struct A : Component { int i; float f; }

    Entity e = world.createEntity(); e.addComponent(1, 0.2f);

    opened by michalkelnar 1
Releases(v2.1.0)
Owner
Miguel Martin
Miguel Martin
apecs: A Petite Entity Component System

apecs: A Petite Entity Component System A header-only, very small entity component system with no external dependencies.

Matt Cummins 17 Jun 1, 2022
EntityX - A fast, type-safe C++ Entity-Component system

EntityX - A fast, type-safe C++ Entity Component System NOTE: The current stable release 1.0.0 breaks backward compatibility with < 1.0.0. See the cha

Alec Thomas 2k Dec 29, 2022
[WIP] Experimental C++14 multithreaded compile-time entity-component-system library.

ecst Experimental & work-in-progress C++14 multithreaded compile-time Entity-Component-System header-only library. Overview Successful development of

Vittorio Romeo 450 Dec 17, 2022
C++ single-header entity component system library

ECS This is a simple C++ header-only type-safe entity component system library. It makes heavy use of C++11 constructs, so make sure you have an up to

Sam Bloomberg 418 Dec 27, 2022
C++ entity-component system

CORGI Version 1.0.2 {#corgi_readme} CORGI is a C++ entity-component system library developed primarily for games that focus on simplicity and flexibil

Google 250 Nov 6, 2022
Entity-Component-System (ECS) with a focus on ease-of-use, runtime extensibility and compile-time type safety and clarity.

Kengine The Koala engine is a type-safe and self-documenting implementation of an Entity-Component-System (ECS), with a focus on runtime extensibility

Nicolas Phister 466 Dec 26, 2022
Thoughts about entity-component-system

About Warning: This is not a complete production-ready library for entity-component-system. This is only my thoughts about how the modern entity-compo

Sergey Makeev 179 Dec 7, 2022
A drop-in entity editor for EnTT with Dear ImGui

imgui_entt_entity_editor A drop-in, single-file entity editor for EnTT, with ImGui as graphical backend. demo-code (live) Editor Editor with Entiy-Lis

Erik Scholz 151 Jan 2, 2023
Open-source and open-hardware scientific RPN calculator

OpenRPNCalc Open-source and open-hardware scientific RPN calculator Introduction OpenRPNCalc is a scientific calculator based on STM32 microcontroller

Anton Poluektov 152 Dec 23, 2022
A fully-functional open source and open hardware mechanical USB computer keyboard with only three keys!

threeboard threeboard is a fully-functional open source and open hardware mechanical USB computer keyboard with only three keys. It supports multiple

Conor Taylor 98 Dec 9, 2022
SynapseOS is a free and open source 64x operating system written in FASM and C

SynapseOS SynapseOS is a free and open source 64x operating system written in FASM and C Documentation Documentation Build To build SynapseOS you need

Synapse OS 102 Dec 5, 2022
Open-source node system framework, to change your algorithmic code into useful tools to create much more complicated simulations!

Open-source node system framework, to change your algorithmic code into useful tools to create much more complicated simulations!

Zenus Technology 763 Jan 9, 2023
Open source selfhosted web-based wiki/doc/knowledge management and collaboration system

Tsailun - open source online document and collaboration Open source selfhosted web-based wiki/doc/knowledge management and collaboration system Access

null 125 Dec 30, 2022
Open Source Cheat for Apex Legends, designed for ease of use. Made to understand reversing of Apex Legends and respawn's modified source engine as well as their Easy Anti Cheat Implementation.

Apex-Legends-SDK Open Source Cheat for Apex Legends, designed for ease of use. Made to understand reversing of Apex Legends and respawn's modified sou

null 111 Jan 8, 2023
Sourcetrail - free and open-source interactive source explorer

Sourcetrail Important Note: This project was archived by the original autors and maintainers of Sourcetrail by the end of 2021. If you want to know mo

Coati Software 13.1k Jan 1, 2023
Single source file ASTC texture decompression in C++ (derived from Google's open source Android project)

astc_dec astc_dec is a single source file ASTC texture decompressor with the Apache 2.0 license, derived from Google's open source Android sources. Th

Rich Geldreich 29 Dec 5, 2022
Following Automotive Open System Architecture (AUTOSAR)

Following Automotive Open System Architecture (AUTOSAR), Diagnostic Communication Manager Module Implemented over Communication Stack Based on AUTOSAR Specification Document (SWS) Release 4.3.1 Classic Platform, ISO-14229 Standard (Road Vehicle Unified Diagnostic Services (UDS)) and ISO-15765 (Road Vehicle Diagnostics on Controller Area Network (CAN)).

null 11 Dec 8, 2022
Operating system project - implementing scheduling algorithms and some system calls for XV6 OS

About XV6 xv6 is a modern reimplementation of Sixth Edition Unix in ANSI C for multiprocessor x86 and RISC-V systems.

Amirhossein Rajabpour 22 Dec 22, 2022
CQC (Charmed Quark Controller) a commercial grade, full featured, software based automation system. CQC is built on our CIDLib C++ development system, which is also available here on GitHub.

The CQC Automation System What It Is CQC is a commercial quality, software based automation system, suitable for residential or commercial application

Dean Roddey 61 Dec 13, 2022