• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
  • entries
    10
  • comments
    51
  • views
    41819

C++ Port of Artemis Entity Component System Framework (In Progress)

Sign in to follow this  
Followers 0
ZachBethel

17216 views

This month is officially "wrap my head around Entity/Component Systems" month. I stepped away from coding for a bit and spent time researching different designs for handling game objects. Most interestingly, my search brought me to the Artemis Entity System Framework. Written in Java, the system is the best overall design I have seen so far (that's not saying much)--even if it is written in Java...just kidding. At any rate, I really liked what I saw so I used it as a reference for my system written in C++. In a way, it's really more like a port, without the reliance on RTTI (or whatever that class identification business is in Java). The architecture is virtually the same, but I took the liberty of writing things a bit differently to reflect the language differences.

Initially I considered using an std::map to relate entities to their component lists, but I really liked that they used a vector in Artemis to store all the entities. An O(1) lookup time is much better than O(log n) when you're dealing with several lookups per entity per frame. Like in Artemis, I opted to use a separate vector with removed entity indices. Whenever an entity is added, the system checks that vector first to see if there is a hole in the main vector. This reduces fragmentation and covers the case where the user removes several entities before adding one.

Unlike Artemis, I used an event system to decouple the entity manager and entity systems. The entity manager fires an event whenever a component is added, allowing the entity systems to check that the entity still has all of the required components. I figured that my game will use an event manager, so it made sense to integrate one now. Also, other subsystems could be notified whenever an entity is created/destroyed or a component is inserted/removed from a specific entity. The entity systems themselves contain a std::set< Entity* > data structure that holds all of the active entities. When it receives one of the previously mentioned events, it can check the entity to see if it should be added to or removed from the set.

Here's what I have so far in my main.cpp test program:


// Create the event manager and entity manager
evtMgr = new SGF::EventManager();
entMgr = new SGF::EntityManager( evtMgr );
test = new SGF::TestSystem(evtMgr, entMgr);

// Create an entity
SGF::Entity *e = entMgr->CreateEntity();
SGF::Transform *trans = new SGF::Transform();
entMgr->InsertComponent(e, trans);

while( !wnd.HasQuit() )
{
wnd.PumpMessages();
ID3D11DeviceContext *dc = graphics->GetImmDeviceContext();
IDXGISwapChain *sc = wnd.GetSwapChain();
{
wnd.SetAsRenderTarget(dc);
dc->ClearDepthStencilView(wnd.GetDSView(), 0, 1.0f, 0);
dc->ClearRenderTargetView(wnd.GetRTView(), D3DXCOLOR(0.0f,0.0f,1.0f,1.0f));
sc->Present(1, 0);
}

// This loops through any entities that match the bit flags for the component type. In this case, all it wants is a Transform component.
test->Process();
}

entMgr->DestroyEntity(e);
delete test;
delete entMgr;
delete evtMgr;


Here's the source for my TestSystem class:


// TestSystem.h /////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __TEST_SYSTEM_H__
#define __TEST_SYSTEM_H__

#include "EntityProcessingSystem.h"

namespace SGF
{
class TestSystem : public EntityProcessingSystem {
public:
TestSystem( EventManager *eventManager, EntityManager *entityManager );
virtual ~TestSystem();

protected:

static unsigned int TypeBits;
virtual void ProcessEntity( EntityManager *manager, Entity *e );
};
};


#endif

// TestSystem.cpp /////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////


#include "TestSystem.h"
#include "EntityManager.h"
#include "ComponentMapper.h"
#include "Transform.h"
#include

using namespace SGF;

unsigned int TestSystem::TypeBits = (1 << CT_TRANSFORM);

TestSystem::TestSystem( EventManager *eventManager, EntityManager *entityManager )
: EntityProcessingSystem(eventManager, entityManager, TypeBits)
{}

TestSystem::~TestSystem() {}

void TestSystem::ProcessEntity( EntityManager *manager, Entity *e )
{
// Allows you to map the list as a specific component type.
ComponentMapper tmap = manager->GetComponentList(e, CT_TRANSFORM);

// We can index a specific component of a specific type.
assert( 0 && tmap[0]->mat._11 );
}


If you look closely at the last line, you'll notice that the component system supports multiple components per type. This is another difference from the Artemis framework, which only allows one per type. The reason I chose to diverge from their design in that respect is because I can think of at least a few key cases where it would be really nice to have multiple components per type. For instance, if I have an articulate vehicle entity, I might have the chassis connected to the wheels. With this system, I could have four joint components--each one connected to a wheel.

At any rate. If anyone is interested in the code, I'd be happy to provide it. It's essentially just a port of Artemis with a couple nuanced changes and additions.

EDIT: I got sidetracked and I haven't made much progress since this post. I decided I would just post what I have: http://cse.taylor.edu/~zbethel/ArtemisPortCpp.zip

If you have any questions, feel free to ask.

0
Sign in to follow this  
Followers 0


10 Comments


Are you using the bit-Identifier approach? if so, are you ok working within the 64 system/component-type limitation? Also, I'm interested in the speed of the event updates vs the cascading updates.
0

Share this comment


Link to comment
Here's what the EntitySystem event code looks like:

[CODE]
bool EntitySystem::HandleEvent( IEventData const &evt )
{
EventType type = evt.GetType();
switch( type )
{
case ET_INSERT_COMPONENT:
case ET_REMOVE_COMPONENT:
{
const EntityEvent &data = static_cast<const EntityEvent&>( evt );
Entity *e = data.e;

// Does this entity meet our requirements?
if( ( e->_typeBits & _typeBits ) == _typeBits )
_actives.insert(e);
else
_actives.erase(e);

break;
}
}

return false;
}
[/CODE]

Yes, it does use bit identifiers.
0

Share this comment


Link to comment
interesting. Though, would you be able to remove the bit-check entirely if you moved the bit check into the initialization phase and then just registered the listener to a static event thrower in the type at that point? That way systems would receive events only from the types they care about. Or would that not work / be too much overhead?
0

Share this comment


Link to comment
It could be done that way also. In my case, I don't foresee needing anywhere close to 64 component types, so I'm not worried about it. If I did happen to hit that restriction though, I could do something like what you mentioned.
0

Share this comment


Link to comment
If you don't want to have to worry about the 64 bit limitation in the future maybe you could use std::bitset and be done with it?
0

Share this comment


Link to comment
I could do that, however I am trying to curb my instinct to do the more complex solution when a simple one makes sense for my application. If I know that I won't go over 64 components, why bother using a data structure that is more flexible, but will slow things down? Just a thought. If I were doing a general port that I planned on releasing as a "do it all" system, you're right, a bitset might be the best solution. Thanks for the suggestion! :)
0

Share this comment


Link to comment
It is just day before yesterday I found Artemis Framework and it is yesterday I have decided to port it into C++. I have not started yet. It would be very nice if you could share your code.
Thank you!
0

Share this comment


Link to comment
I'd really like to use this in cocos2d-x to make a game for iOS but it looks like its dependent on DirectX. Do you have an implementation that doesn't have any dependencies?
0

Share this comment


Link to comment
Hi Zach,

I've recently been playing with my own entity component system and came up against the issue of multiple components of the same type per entity - I've ended up getting around it by having different entities (in your case, for wheels) where each wheel would have an AttachmentPoint with a relative position and a reference to the 'car' entity id. That way, a separate system can handle everything with AttachmentPoint and translate accordingly. What are your thoughts about this approach?
0

Share this comment


Link to comment
Hey, sorry for not responding earlier. I haven't checked my blog in a little while.

I'm sure you could work with that approach. I've thought extensively about going that route. The use case that keeps bothering me though is that of an articulate physics object. If you have a ragdoll dozens of joints and body parts, are you going to represent that as dozens of individual entities all referencing each other? Although you could do it that way, you're going to need a higher level 'super entity' to manage all the dependencies. I like to think about entities as full prefab objects that I would add to a game editor. Take for instance, the Forge editor in Halo. Your character is an entity, a warthog is an entity, etc. The warthog, for instance, has four wheels and a turret that I imagine are governed by their own unique transform and mesh components. If you represent all of those as entities, you suddenly have an explosion of entities in your game editor. You would need a higher level entity to manage those.

The nice thing about handling interconnected parts of a game object as components rather than sub-entities is that you can kill the entire object with the entity. Like, when the warthog blows up, you might break the constraints holding the wheels onto the vehicle, and then let the wheels bounce around. They're still part of the same 'entity' (the warthog), and when the warthog disappears after a certain amount of time, the wheels magically disappear with it.

Also, I lean more towards giving each component a direct pointer to it's dependencies. For instance, your model component needs transform component to orient it. That transform component could be controlled by the RigidBody component. So essentially, your model just needs a constant reference to the transform, while the rigid body needs a writable pointer.

There is no perfect way to handle this problem. If you've figured out ways to solve these problems with your method I'd love to hear about it!
0

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now