313 lines
9.1 KiB
Python
313 lines
9.1 KiB
Python
import sys
|
|
import unittest
|
|
from ..ext.ebs import Entity, System, Applicator, World
|
|
|
|
|
|
class Position(object):
|
|
def __init__(self, x=0, y=0):
|
|
self.x = x
|
|
self.y = y
|
|
|
|
def __eq__(self, other):
|
|
return self.x == other.x and self.y == other.y
|
|
|
|
|
|
class Movement(object):
|
|
def __init__(self, vx=0, vy=0):
|
|
self.vx = vx
|
|
self.vy = vy
|
|
|
|
|
|
class PositionEntity(Entity):
|
|
def __init__(self, world, x=0, y=0):
|
|
self.position = Position(x, y)
|
|
|
|
|
|
class MovingEntity(Entity):
|
|
def __init__(self, world, x=0, y=0, vx=0, vy=0):
|
|
self.position = Position(x, y)
|
|
self.movement = Movement(vx, vy)
|
|
|
|
|
|
class PosEntity(Entity):
|
|
def __init__(self, world, x=0, y=0):
|
|
self.pos = Position(x, y)
|
|
|
|
|
|
class PositionSystem(System):
|
|
def __init__(self):
|
|
super(PositionSystem, self).__init__()
|
|
self.componenttypes = (Position,)
|
|
|
|
def process(self, world, components):
|
|
for c in components:
|
|
c.x += 1
|
|
c.y += 1
|
|
|
|
|
|
class MovementApplicator(Applicator):
|
|
def __init__(self):
|
|
super(MovementApplicator, self).__init__()
|
|
self.componenttypes = (Position, Movement)
|
|
|
|
def process(self, world, componentsets):
|
|
for p, m in componentsets:
|
|
p.x += m.vx
|
|
p.y += m.vy
|
|
|
|
|
|
class SDL2ExtEBSTest(unittest.TestCase):
|
|
__tags__ = ["ebs", "sdl2ext"]
|
|
|
|
def test_Entity(self):
|
|
world = World()
|
|
world.add_system(PositionSystem())
|
|
|
|
e = Entity(world)
|
|
e2 = Entity(world)
|
|
self.assertIsInstance(e, Entity)
|
|
self.assertIsInstance(e2, Entity)
|
|
self.assertNotEqual(e, e2)
|
|
|
|
p = PositionEntity(world)
|
|
self.assertIsInstance(p, PositionEntity)
|
|
self.assertIsInstance(p, Entity)
|
|
|
|
def test_Entity_id(self):
|
|
world = World()
|
|
ent1 = Entity(world)
|
|
ent2 = Entity(world)
|
|
self.assertNotEqual(ent1.id, ent2.id)
|
|
|
|
def test_Entity_world(self):
|
|
world = World()
|
|
world2 = World()
|
|
ent1 = Entity(world)
|
|
ent2 = Entity(world2)
|
|
self.assertEqual(ent1.world, world)
|
|
self.assertNotEqual(ent1.world, world2)
|
|
self.assertEqual(ent2.world, world2)
|
|
self.assertNotEqual(ent2.world, world)
|
|
self.assertNotEqual(ent1.world, ent2.world)
|
|
|
|
def test_Entity_delete(self):
|
|
w = World()
|
|
e1 = Entity(w)
|
|
e2 = Entity(w)
|
|
|
|
self.assertEqual(len(w.entities), 2)
|
|
e1.delete()
|
|
self.assertEqual(len(w.entities), 1)
|
|
e2.delete()
|
|
self.assertEqual(len(w.entities), 0)
|
|
|
|
# The next two should have no effect
|
|
e1.delete()
|
|
e2.delete()
|
|
|
|
def test_Entity__inheritance(self):
|
|
world = World()
|
|
|
|
pos1 = PositionEntity(world)
|
|
pos2 = PositionEntity(world, 10, 10)
|
|
for p in (pos1, pos2):
|
|
self.assertIsInstance(p, PositionEntity)
|
|
self.assertIsInstance(p, Entity)
|
|
self.assertIsInstance(p.position, Position)
|
|
|
|
def test_Entity__access(self):
|
|
world = World()
|
|
pos1 = PositionEntity(world)
|
|
pos2 = PosEntity(world)
|
|
|
|
pos1.position.x = 10
|
|
|
|
# components are _always_ identified by a lower-case class name.
|
|
def sx(p, v):
|
|
p.pos.x = v
|
|
self.assertRaises(AttributeError, sx, pos2, 10)
|
|
|
|
def test_World(self):
|
|
w = World()
|
|
self.assertIsInstance(w, World)
|
|
|
|
def test_World_add_remove_system(self):
|
|
world = World()
|
|
self.assertIsInstance(world, World)
|
|
|
|
class SimpleSystem(object):
|
|
def __init__(self):
|
|
self.componenttypes = (Position,)
|
|
|
|
def process(self, world, components):
|
|
pass
|
|
|
|
for method in (world.add_system, world.remove_system):
|
|
for val in (None, "Test", Position, Entity(world)):
|
|
self.assertRaises(ValueError, method, val)
|
|
|
|
psystem = SimpleSystem()
|
|
world.add_system(psystem)
|
|
self.assertTrue(len(world.systems) != 0)
|
|
self.assertTrue(psystem in world.systems)
|
|
world.remove_system(psystem)
|
|
self.assertTrue(len(world.systems) == 0)
|
|
self.assertTrue(psystem not in world.systems)
|
|
|
|
psystem = PositionSystem()
|
|
world.add_system(psystem)
|
|
self.assertTrue(len(world.systems) != 0)
|
|
self.assertTrue(psystem in world.systems)
|
|
|
|
entity = PositionEntity(world)
|
|
self.assertIsInstance(entity.position, Position)
|
|
|
|
world.remove_system(psystem)
|
|
self.assertTrue(len(world.systems) == 0)
|
|
self.assertTrue(psystem not in world.systems)
|
|
|
|
# The data must stay intact in the world, even if the processing
|
|
# system has been removed.
|
|
self.assertIsInstance(entity.position, Position)
|
|
|
|
def test_World_entities(self):
|
|
w = World()
|
|
self.assertEqual(len(w.entities), 0)
|
|
|
|
for x in range(100):
|
|
Entity(w)
|
|
self.assertEqual(len(w.entities), 100)
|
|
|
|
def test_World_delete(self):
|
|
w = World()
|
|
e1 = Entity(w)
|
|
e2 = Entity(w)
|
|
|
|
self.assertEqual(len(w.entities), 2)
|
|
w.delete(e1)
|
|
self.assertEqual(len(w.entities), 1)
|
|
w.delete(e2)
|
|
self.assertEqual(len(w.entities), 0)
|
|
|
|
# The next two should have no effect
|
|
w.delete(e1)
|
|
w.delete(e2)
|
|
|
|
def test_World_delete_entities(self):
|
|
w = World()
|
|
e1 = Entity(w)
|
|
e2 = Entity(w)
|
|
|
|
self.assertEqual(len(w.entities), 2)
|
|
w.delete_entities((e1, e2))
|
|
self.assertEqual(len(w.entities), 0)
|
|
# The next should have no effect
|
|
w.delete_entities((e1, e2))
|
|
|
|
def test_World_get_entities(self):
|
|
w = World()
|
|
e1 = PositionEntity(w, 1, 1)
|
|
e2 = PositionEntity(w, 1, 2)
|
|
self.assertEqual(len(w.get_entities(e1.position)), 1)
|
|
e2.position.y = 1
|
|
self.assertEqual(len(w.get_entities(e1.position)), 2)
|
|
|
|
def test_System(self):
|
|
world = World()
|
|
self.assertRaises(ValueError, world.add_system, None)
|
|
self.assertRaises(ValueError, world.add_system, 1234)
|
|
self.assertRaises(ValueError, world.add_system, "Test")
|
|
|
|
class ErrornousSystem(System):
|
|
def __init__(self):
|
|
super(ErrornousSystem, self).__init__()
|
|
|
|
esystem = ErrornousSystem()
|
|
# No component types defined.
|
|
self.assertRaises(ValueError, world.add_system, esystem)
|
|
self.assertEqual(len(world.systems), 0)
|
|
|
|
psystem = PositionSystem()
|
|
world.add_system(psystem)
|
|
self.assertTrue(psystem in world.systems)
|
|
|
|
def test_System_process(self):
|
|
world = World()
|
|
|
|
class ErrornousSystem(System):
|
|
def __init__(self):
|
|
super(ErrornousSystem, self).__init__()
|
|
self.componenttypes = (Position,)
|
|
|
|
esystem = ErrornousSystem()
|
|
world.add_system(esystem)
|
|
for x in range(10):
|
|
PositionEntity(world)
|
|
self.assertTrue(esystem in world.systems)
|
|
self.assertRaises(NotImplementedError, world.process)
|
|
|
|
world2 = World()
|
|
psystem = PositionSystem()
|
|
world2.add_system(psystem)
|
|
for x in range(10):
|
|
PositionEntity(world2)
|
|
self.assertTrue(psystem in world2.systems)
|
|
world2.process()
|
|
for c in world2.components[Position].values():
|
|
self.assertEqual(c.x, 1)
|
|
self.assertEqual(c.y, 1)
|
|
world2.process()
|
|
for c in world2.components[Position].values():
|
|
self.assertEqual(c.x, 2)
|
|
self.assertEqual(c.y, 2)
|
|
|
|
def test_Applicator(self):
|
|
world = World()
|
|
|
|
class ErrornousApplicator(Applicator):
|
|
def __init__(self):
|
|
super(ErrornousApplicator, self).__init__()
|
|
|
|
eapplicator = ErrornousApplicator()
|
|
# No component types defined.
|
|
self.assertRaises(ValueError, world.add_system, eapplicator)
|
|
self.assertEqual(len(world.systems), 0)
|
|
|
|
mapplicator = MovementApplicator()
|
|
world.add_system(mapplicator)
|
|
self.assertTrue(mapplicator in world.systems)
|
|
|
|
def test_Applicator_process(self):
|
|
world = World()
|
|
|
|
class ErrornousApplicator(Applicator):
|
|
def __init__(self):
|
|
super(ErrornousApplicator, self).__init__()
|
|
self.componenttypes = (Position, Movement)
|
|
|
|
eapplicator = ErrornousApplicator()
|
|
world.add_system(eapplicator)
|
|
for x in range(10):
|
|
MovingEntity(world)
|
|
self.assertTrue(eapplicator in world.systems)
|
|
self.assertRaises(NotImplementedError, world.process)
|
|
|
|
world2 = World()
|
|
mapplicator = MovementApplicator()
|
|
world2.add_system(mapplicator)
|
|
for x in range(10):
|
|
MovingEntity(world2, vx=1, vy=1)
|
|
self.assertTrue(mapplicator in world2.systems)
|
|
world2.process()
|
|
for c in world2.components[Position].values():
|
|
self.assertEqual(c.x, 1)
|
|
self.assertEqual(c.y, 1)
|
|
world2.process()
|
|
for c in world2.components[Position].values():
|
|
self.assertEqual(c.x, 2)
|
|
self.assertEqual(c.y, 2)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(unittest.main())
|