Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!

1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Member Since 25 Jun 2011
Offline Last Active Sep 20 2012 04:39 AM

#4929702 Using RTTI in an entity component system?

Posted by GorbGorb on 09 April 2012 - 05:51 PM

I mentioned JavaScript above:

var Enemy = function() {
  this.velocity = [1.0, 2.0, 3.0];
  this.mass = 200.0;


With some template magic and type erasure this can actually be emulated in c++, for example, I use this:
prototype p = system_manager.new_prototype();
p.add_component( velocitity{ x , y , z } );
p.add_component( mass{ 200 } );
entity a = system_manager.new_entity( p );
entity b = system_manager.new_entity( p );
which doesn't look that much worse. The idea is to have references to base_system s in your system_manager. During its initialization, you create a map< typeinfo , unsigned int >, where the value type is unsigned int. When adding a component to a prototype (usually while loading a level) you lookup that system_index in the map once and store it with the component. To create an entity from a prototype you simply iterate over all components in it and do
systems[ system_id ].insert( component );

Maybe I'll refactor my implementation a bit and upload it somewhere, it is, as you said, quite some work to implement a generic component system in c++.

#4916170 Organizing and managing code?

Posted by GorbGorb on 24 February 2012 - 06:00 AM

-Every time you use a 'new' keyword to allocate memory, automatically create a 'delete' keyword to deallocate it and make sure that the delete is reached.

Don't use new unless you need a custom data structure or for unique_ptr. Use std::make_shared and std::vector instead (you could also create std::make_unique, I'm sure it'll make it into the standard soon).
A *a = new A;
//use a
delete a;
is very like not exception safe. Better:
std::unique_ptr< A > a( new A() );
//use a
//std::unique_ptr deletes a
You don't leak memory if you use modern c++.

#4872504 C++ template class, specialized member function/operator

Posted by GorbGorb on 14 October 2011 - 07:11 AM

template<typename T> class Foo


	T m;


	operator int() const


		return int(m);


	//Lots of other member functions ect.



Foo<int>::operator int() const


	//specialized version

	return 0;


#4859437 [C++] Looking for feedback on my event system

Posted by GorbGorb on 09 September 2011 - 05:24 AM

Ok, although I don't use std::function too often, I noticed some things to improve:
- you are leaking memory
- why don't you just let users register a std::function object directly?

In addition, you could hide some boilerplate (event id , event base ) with this technique:

unsigned int next_id()
  unsigned int previous_id = 0;
  return ++previous_id; //or return previous_id++ , depending on wheter you need a NULL value
template< class Type >
class type_id
  static unsigned int value;
template< class Type >
unsigned int type_id< Type >::value = next_id(); //unique value for each type
After that, the register and disptach functions would just look like this:
template< class EventType >
void register( std::function< void( const EventType &) > callback )
  unsigned int id = type_id< EventType >::value;
template< class EventType >
void dispatch( const EventType &event )
  unsigned int id = type_id< EventType >::value;
That way, you can use any type you want (e.g. an int or an std::string) as an EventType and save a lot of boilerplate and bugs because you can't accidentally use a wrong event id.

To save the map lookup, you could use a vector whose size is as big as the number of EventType s you have instead of a map.
(to do is, check in register and dispatch whether your vector is large enough and resize it if needed).
Then you can just access the listener_vector for any type T with
listener_vectors[ type_id< T >::value ];
which has O(1), but probably consumes more memory if you have multiple dispatchers.