def __init__(self): """Creates an empty Entity""" #collection that holds all the components indexed by their ComponentType index self.components = {} #auxiliary array for user access to all the components of an entity self.components_array = [] #a flag that can be used to bit mask this entity (user managed) self.flags = 0 #will dispatch an event when a component is added self.component_added = Signal() #will dispatch an event when a component is removed self.component_removed = Signal() #describing all the components in this entity for quick matching self.component_bits = Bits() #describing all the systems this entity was matched with self.family_bits = Bits() self.index = Entity.next_index Entity.next_index += 1
def get_bits_for(cls, *component_classes): """return bits representing the collection of components for quick comparison and matching. See Family get_for(bits, bits, bits)""" bits = Bits() type_classes_length = len(component_classes) for i in range(type_classes_length): bits.set(cls.get_index_for(component_classes[i])) return bits
def test_bits_logic_or(self): b1 = Bits(12) b2 = Bits(66) b1.set(0) b1.set(12) b2.set(12) b2.set(65) b3 = b1.logic_or(b2) self.assertEqual(b3.to_bitstr(), "1" + "0"*11 + "1" + "0"*50) b4 = b2.logic_or(b1) self.assertEqual(b4.to_bitstr(), "1" + "0"*11 + "1" + "0"*50 + "0"*2 + "1" + "0"*60)
def test_bits_length(self): b = Bits(12) b.set(5) length = b.length() self.assertEqual(length, 5) b.set(127) length = b.length() self.assertEqual(length, 127) b.clear() length = b.length() self.assertEqual(length, 0)
def get_for_bits(cls, bits_all=Bits(), bits_one=Bits(), bits_exclude=Bits()): """bits_all: all entities will have to contain all of the components in the set bits_one: entities will have to contain at least one of the components in the set bits_exclude: entities cannot contain nay of the components in the set""" family_hash = cls.get_family_hash(bits_all, bits_one, bits_exclude) if family_hash in cls.families: return cls.families[family_hash] else: family = cls(bits_all, bits_one, bits_exclude) cls.families[family_hash] = family return family
def __init__(self, bits_all=Bits(), bits_one=Bits(), bits_exclude=Bits()): """Private constructor, don't use this. Use Family.getFamilyFor() instead""" #must contain all the components in the set self.bits_all = bits_all #must contain at least one of the components in the set self.bits_one = bits_one #cannot contain any of the components in the set self.bits_exclude = bits_exclude #each family has a unique index used for bitmasking self.index = Family.next_index Family.next_index += 1
def test_bits_capacity(self): b = Bits(8) self.assertEqual(b.to_bitstr(), "0"*63) b = Bits(1) self.assertEqual(b.to_bitstr(), "0"*63) b = Bits(63) self.assertEqual(b.to_bitstr(), "0"*63) b = Bits(64) self.assertEqual(b.to_bitstr(), "0"*126)
def test_bits_next_set(self): b = Bits(12) b.set(0) b.set(10) i = b.next_set_bit(2) self.assertEqual(i, 10) i = b.next_set_bit(12) self.assertEqual(i, None) b.set(67) i = b.next_set_bit(12) self.assertEqual(i, 67) b = Bits(12) b.set(170) i = b.next_set_bit(12) self.assertEqual(i, 170)
def test_bits_clear(self): b = Bits(12) b.set(0) b.set(5) b.clear() self.assertEqual(b.to_bitstr(), "0" * 63) b.set(1) b.set(2) b.clear(2) self.assertEqual(b.to_bitstr(), "01" + "0" * 61)
def test_bits_constructor(self): b = Bits(127, [0, 1]) self.assertEqual(b.to_bitstr(), "0" * 63 + "1" + "0" * 62)
def test_bits_get(self): b = Bits(12) b.set(6) self.assertEqual(b.get(6), True) self.assertEqual(b.get(2), False)
def test_bits_capacity_grow(self): b = Bits(1) b.set(64) self.assertEqual(b.to_bitstr(), "0" * 63 + "01" + "0" * 61)
def test_bits_set(self): b = Bits(64) b.set(0) self.assertEqual(b.to_bitstr(), "1" + "0"*125) b = Bits(1) b.set(62) self.assertEqual(b.to_bitstr(), "0"*62 + "1") b = Bits(1) b.set(63) self.assertEqual(b.to_bitstr(), "0"*63 + "1" + "0"*62)
def test_bits_capacity_grow(self): b = Bits(1) b.set(64) self.assertEqual(b.to_bitstr(), "0"*63 + "01" + "0"*61)
def test_num_bits(self): b = Bits(12) self.assertEqual(b.num_bits(), 64) b.set(110) self.assertEqual(b.num_bits(), 128)
def get_for_classes(cls, *component_classes): """returns a family with the passed Component classes as a descriptor. each set of component types will always return the same family instance.""" return cls.get_for_bits(ComponentType.get_bits_for(*component_classes), Bits(), Bits())
def test_bits_set(self): b = Bits(64) b.set(0) self.assertEqual(b.to_bitstr(), "1" + "0" * 125) b = Bits(1) b.set(62) self.assertEqual(b.to_bitstr(), "0" * 62 + "1") b = Bits(1) b.set(63) self.assertEqual(b.to_bitstr(), "0" * 63 + "1" + "0" * 62)
def test_bits_flip(self): b = Bits(63) b.set(0) b.set(2) b.flip(2) self.assertEqual(b.to_bitstr(), "1" + "0"*62) b = Bits(64) b.set(63) b.set(65) b.flip(63) self.assertEqual(b.to_bitstr(), "0"*63 + "0"*2 + "1" + "0"*60)
def test_bits_flip(self): b = Bits(63) b.set(0) b.set(2) b.flip(2) self.assertEqual(b.to_bitstr(), "1" + "0" * 62) b = Bits(64) b.set(63) b.set(65) b.flip(63) self.assertEqual(b.to_bitstr(), "0" * 63 + "0" * 2 + "1" + "0" * 60)
def test_bits_constructor(self): b = Bits(127, [0,1]) self.assertEqual(b.to_bitstr(), "0"*63 + "1" + "0"*62)
def test_bits_logic_or(self): b1 = Bits(12) b2 = Bits(66) b1.set(0) b1.set(12) b2.set(12) b2.set(65) b3 = b1.logic_or(b2) self.assertEqual(b3.to_bitstr(), "1" + "0" * 11 + "1" + "0" * 50) b4 = b2.logic_or(b1) self.assertEqual( b4.to_bitstr(), "1" + "0" * 11 + "1" + "0" * 50 + "0" * 2 + "1" + "0" * 60)
class Entity(object): """Simple containers of Components that give them "data". The component's data is then processed by EntitySystem's""" #static next_index=0 def __init__(self): """Creates an empty Entity""" #collection that holds all the components indexed by their ComponentType index self.components = {} #auxiliary array for user access to all the components of an entity self.components_array = [] #a flag that can be used to bit mask this entity (user managed) self.flags = 0 #will dispatch an event when a component is added self.component_added = Signal() #will dispatch an event when a component is removed self.component_removed = Signal() #describing all the components in this entity for quick matching self.component_bits = Bits() #describing all the systems this entity was matched with self.family_bits = Bits() self.index = Entity.next_index Entity.next_index += 1 def get_component_by_class(self, component_class): return self.get_component(ComponentType.get_for(component_class)) def get_components(self): return self.components_array def get_component_bits(self): """This Entity's Component bits, describing all the Component's it contains""" return self.component_bits def get_family_bits(self): """This Entity's Family bits, describing all the EntitySystem's it is currently being processed by""" return self.family_bits def get_component(self, component_type): """return the Component object for the specified class. None if the Entity does not have any components for that class""" component_type_index = component_type.get_index() if component_type_index < len(self.components): return self.components[component_type.get_index()] else: return None def has_component(self, component_class): return self.component_bits.get(component_class.get_index()) def get_index(self): """return the Etity's unique index""" return self.index; def add(self, component): """Adds a Component to this Entity. If a Component of the same type already exists, it will be replaced. Returns self for easy chaining""" component_class = component.__class__ for c in self.components_array: if c.__class__ == component_class: del self.components_array[c] break component_class_index = ComponentType.get_index_for(component_class) self.components[component_class_index] = component self.components_array.append(component) self.component_bits.set(component_class_index) self.component_added(self) return self def remove(self, component_class): """Removes the Componenet of the specified type. Since there is only ever one component of one type, we don't need an instance reference. returns the removed component""" component_class_index = ComponentType.get_index_for(component_class) remove_component = self.components[component_class_index] if remove_component != None: del self.components[component_class_index] self.components_array.remove(remove_component) self.component_bits.clear(index=component_class_index) self.component_removed(self) def remove_all(self): """removes all the Components from an Entity""" while len(self.components_array) > 0: self.remove(self.components_array[0].__class__) def hash_code(self): return self.index def __eq__(self, other): if self is other: return True if other == None: return False if not issubclass(other.__class__, Entity): return False return self.index == other.index def __ne__(self, other): return not self.__eq__(other)
def test_bits_capacity(self): b = Bits(8) self.assertEqual(b.to_bitstr(), "0" * 63) b = Bits(1) self.assertEqual(b.to_bitstr(), "0" * 63) b = Bits(63) self.assertEqual(b.to_bitstr(), "0" * 63) b = Bits(64) self.assertEqual(b.to_bitstr(), "0" * 126)
def test_bits_clear(self): b = Bits(12) b.set(0) b.set(5) b.clear() self.assertEqual(b.to_bitstr(), "0"*63) b.set(1) b.set(2) b.clear(2) self.assertEqual(b.to_bitstr(), "01" + "0"*61)
class Entity(object): """Simple containers of Components that give them "data". The component's data is then processed by EntitySystem's""" #static next_index = 0 def __init__(self): """Creates an empty Entity""" #collection that holds all the components indexed by their ComponentType index self.components = {} #auxiliary array for user access to all the components of an entity self.components_array = [] #a flag that can be used to bit mask this entity (user managed) self.flags = 0 #will dispatch an event when a component is added self.component_added = Signal() #will dispatch an event when a component is removed self.component_removed = Signal() #describing all the components in this entity for quick matching self.component_bits = Bits() #describing all the systems this entity was matched with self.family_bits = Bits() self.index = Entity.next_index Entity.next_index += 1 def get_component_by_class(self, component_class): return self.get_component(ComponentType.get_for(component_class)) def get_components(self): return self.components_array def get_component_bits(self): """This Entity's Component bits, describing all the Component's it contains""" return self.component_bits def get_family_bits(self): """This Entity's Family bits, describing all the EntitySystem's it is currently being processed by""" return self.family_bits def get_component(self, component_type): """return the Component object for the specified class. None if the Entity does not have any components for that class""" component_type_index = component_type.get_index() if component_type_index < len(self.components): return self.components[component_type.get_index()] else: return None def has_component(self, component_class): return self.component_bits.get(component_class.get_index()) def get_index(self): """return the Etity's unique index""" return self.index def add(self, component): """Adds a Component to this Entity. If a Component of the same type already exists, it will be replaced. Returns self for easy chaining""" component_class = component.__class__ for c in self.components_array: if c.__class__ == component_class: del self.components_array[c] break component_class_index = ComponentType.get_index_for(component_class) self.components[component_class_index] = component self.components_array.append(component) self.component_bits.set(component_class_index) self.component_added(self) return self def remove(self, component_class): """Removes the Componenet of the specified type. Since there is only ever one component of one type, we don't need an instance reference. returns the removed component""" component_class_index = ComponentType.get_index_for(component_class) remove_component = self.components[component_class_index] if remove_component != None: del self.components[component_class_index] self.components_array.remove(remove_component) self.component_bits.clear(index=component_class_index) self.component_removed(self) def remove_all(self): """removes all the Components from an Entity""" while len(self.components_array) > 0: self.remove(self.components_array[0].__class__) def hash_code(self): return self.index def __eq__(self, other): if self is other: return True if other == None: return False if not issubclass(other.__class__, Entity): return False return self.index == other.index def __ne__(self, other): return not self.__eq__(other)