#include // Component-entity system in 24 lines of C++11. 2013 rlyeh, MIT licensed. #include // Code fragment from kult engine - https://github.com/r-lyeh/kult enum SUBSYSTEM_MODE { JOIN = 0, MERGE = 1, EXCLUDE = 2 }; template std::set &system() { static std::set entities; return entities; } template std::set subsystem( const std::set &B ) { std::set newset; const std::set &A = system(); // union first, /**/ if (MODE == MERGE) { newset = B; for( auto &id : A ) newset.insert(id); } // then difference, else if (MODE == EXCLUDE) { newset = B; for( auto &id : A ) newset.erase (id); } // then intersection else if(A.size() < B.size()) { for( auto &id : A ) if(B.find(id) != B.end()) newset.insert( id ); } else { for( auto &id : B ) if(A.find(id) != A.end()) newset.insert( id ); } return newset; } template std::map< unsigned, T > &components() { static std::map< unsigned, T > objects; return objects; } template bool has( unsigned id ) { return components().find( id ) != components().end(); } template decltype(T::value_type) &get( unsigned id ) { static decltype(T::value_type) invalid, reset; return has(id) ? components()[id].value_type : invalid = reset; } template decltype(T::value_type) &add( unsigned id ) { return system().insert( id ), components()[id] = components()[id], get(id); } template bool del( unsigned id ) { return add(id), components().erase( id ), system().erase( id ), !has( id ); } template struct component { T value_type; }; // example: #include #include #include // gamedev types and constants typedef std::pair vec2i; typedef std::pair vec2f; const vec2f zero = { 0.f, 0.f }, one = { 1.f, 1.f }; // component aliases using friendly = component< bool, 'team' >; using health = component< int, 'heal' >; using mana = component< int, 'mana' >; using coins = component< int, 'coin' >; using name = component< std::string, 'name' >; using position = component< vec2f, 'pos2' >; // sugars template std::set< unsigned > join() { return subsystem( system() ); } template std::set< unsigned > join() { return subsystem( join() ); } template std::set< unsigned > join() { return subsystem( join() ); } template std::set< unsigned > exclude( const std::set &B ) { return subsystem(B); } int main() { // entities int none = 0, player = 1, enemy = 2; // components assert( !has(player) ); assert( !has(player) ); assert( !has(enemy) ); assert( !has(enemy) ); add(player) = "Hero"; add(player) = zero; add(player) = 100; add(player) = 200; add(player) = 4000; add(player) = true; add(enemy) = "Orc"; add(enemy) = one; add(enemy) = 200; add(enemy) = 50; add(enemy) = 10; assert( get(player) == 100 ); // :> assert( has(player) ); assert( !has(player) ); assert( has(player) ); assert( has(player) ); assert( get(player) == "Hero" ); assert( get(player) == zero ); assert( get(player) == 100 ); // systems; here we intersect a system of all elements with and . assert( (join().size() == 2) ); // systems; render game state auto display = []() { std::cout << "- "; for( auto &id : join() ) { std::cout << get(id) << " at " << "(" << get(id).first << "," << get(id).second << ")" << " " << get(id) << "HP" << " " << get(id) << "$, "; } std::cout << std::endl; }; display(); // systems; simulate movement for( auto &id : join() ) { std::cout << get(id) << " says: im moving!" << std::endl; vec2f &pos = get(id); pos.first += 10; pos.second ++; } // systems; simulate a spell bomb in entities of any type for( auto &id : system() ) { std::cout << "spellboomb!!!" << std::endl; get(id) -= 50; } // systems; simulate a powerup (+$100) for all players for( auto &id : join() ) { get(id) += 100; std::cout << get(id) << " says: money! :)" << std::endl; } // systems; simulate a poison (-50%HP) to all entities that are not friendly (so enemies) for( auto &id : exclude( join() ) ) { get(id) *= 0.5; std::cout << get(id) << " says: ugh! poisoned :(" << std::endl; } display(); assert( get(player) == 100+0 ); assert( get(enemy) == 200/2 ); assert( get(player) == 200+100 ); assert( get(enemy) == 50+0 ); assert( get(player) == 4000-50 ); assert( get(enemy) == 10-50 ); assert( del(player) ); assert( !has(player) ); assert( del(player) ); assert( !has(player) ); assert( (join().size() == 1) ); }