An open source C++ entity system.

Related tags

Game 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 " ([email protected]@anax@@[email protected]@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_p[email protected]@[email protected]@@[email protected]@3@@std@@[email protected])

    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
A fast entity component system (ECS) for C & C++

Flecs is a fast and lightweight Entity Component System with a focus on high performance game development (join the Discord!). Highlights of the frame

Sander Mertens 3.5k Jan 8, 2023
Simple tower defense game using C++ with Entity Component System (ECS)

CubbyTower CubbyTower is a simple tower defense game using C++ with Entity Component System (ECS). The code is built on C++17 and can be compiled with

Chris Ohk 39 Dec 20, 2022
A C++14 Entity Component System

NOTICE: This project is currently in the progress of being rewritten for C++17. Check out this issue if you have any suggestions/know a good way to tr

Elnar Dakeshov 187 Nov 9, 2022
Gaming meets modern C++ - a fast and reliable entity-component system (ECS) and much more

EnTT is a header-only, tiny and easy to use entity-component system (and much more) written in modern C++. Among others, it's also used in Minecraft by Mojang and The Forge by Confetti.

Sean Middleditch 8 Feb 16, 2021
This is a list of different open-source video games and commercial video games open-source remakes.

This is a list of different open-source video games and commercial video games open-source remakes.

Ivan Bobev 173 Jan 2, 2023
Replace Minecraft entity with MMD model.

KAIMyEntity Replace Minecraft entity with MMD model. KAIMyEntitySaba 将Github项目 benikabocha/saba (https://github.com/benikabocha/saba) 魔改成一个以JNI形式Expor

null 30 Oct 16, 2022
OpenMW is an open-source open-world RPG game engine that supports playing Morrowind.

OpenMW is an open-source open-world RPG game engine that supports playing Morrowind.

null 4.5k Jan 2, 2023
VTK is an open-source software system for image processing, 3D graphics, volume rendering and visualization

Introduction VTK is an open-source software system for image processing, 3D graphics, volume rendering and visualization. VTK includes many advanced a

Kitware, Inc. 2k Dec 30, 2022
Open-source, cross-platform, C++ game engine for creating 2D/3D games.

GamePlay v3.0.0 GamePlay is an open-source, cross-platform, C++ game framework/engine for creating 2D/3D mobile and desktop games. Website Wiki API De

gameplay3d 3.9k Jan 8, 2023
KlayGE is a cross-platform open source game engine with plugin-based architecture.

KlayGE KlayGE is a cross-platform open source game engine with plugin-based architecture. It's started since 2003. The explicit goal of KlayGE is: to

Minmin Gong 1.8k Dec 23, 2022
Powerful, mature open-source cross-platform game engine for Python and C++, developed by Disney and CMU

Panda3D Panda3D is a game engine, a framework for 3D rendering and game development for Python and C++ programs. Panda3D is open-source and free for a

Panda3D 3.6k Dec 31, 2022
MIT Licensed Open Source version of Torque 2D game engine from GarageGames

We've moved! All torque engines have moved to a new organization, Torque Game Engines. Torque2D can be found at https://github.com/TorqueGameEngines/T

GarageGames 1.7k Dec 14, 2022
MIT Licensed Open Source version of Torque 3D from GarageGames

Torque 3D MIT Licensed Open Source version of Torque 3D from GarageGames More Information Homepage Torque 3D wiki Community forum GarageGames forum Ga

GarageGames 3.3k Dec 16, 2022
An open source re-implementation of RollerCoaster Tycoon 2 🎢

An open source re-implementation of RollerCoaster Tycoon 2 ??

OpenRCT2 11.3k Jan 3, 2023
Free, open-source, game engine and a 3D sandbox.

Work-in-Progress The official "early alpha" release should be available around April 2021 SGEEngine SGEEngine is an open source (MIT License), C++ cen

ongamex 72 Dec 7, 2022
Project DELTA - An open-source trainer built on the Void Engine for Toby Fox's games and their spin-offs.

Project DELTA v3 Project DELTA - An open-source, modular mod menu for Toby Fox's games and their spin-offs. Important note to Grossley: Yes, it is out

Archie 8 Oct 15, 2022
MAZE (My AmaZing Engine) - 🎮 Personal open-source cross-platform game engine

MAZE (My AmaZing Engine) is the self-written open-source cross-platform game engine in the active development stage. At the moment it is my main pet project, developed for the purpose of learning and preserving different game dev technologies.

Dmitriy Nosov 13 Dec 14, 2022
yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of Citra.

yuzu (Nintendo Switch Emulator) yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of Citra. It is written in C++

null 537 Dec 29, 2022
Vinifera is an open-source community collaboration project extending the Tiberian Sun engine.

Vinifera is an open-source community collaboration project extending the Tiberian Sun engine. Latest Nightly Build: Download Table of Contents Intro C

Vinifera Developers 25 Nov 1, 2022