Factor out ray manager.
authorSimon Cross <hodgestar@gmail.com>
Wed, 7 Sep 2016 20:02:02 +0000 (22:02 +0200)
committerSimon Cross <hodgestar@gmail.com>
Wed, 7 Sep 2016 20:02:02 +0000 (22:02 +0200)
tabakrolletjie/lights.py
tabakrolletjie/rays.py

index 097abd235f2e4b8d53e97f1ecdcc5ed08f2531fe..39b1815fc782b02972ef9d91233d44d7b9b739d8 100644 (file)
@@ -8,7 +8,7 @@ import pygame.draw
 import pygame.locals as pgl
 
 from .constants import LIGHT_CATEGORY, FITTINGS_CATEGORY
-from .rays import calculate_ray_polys
+from .rays import RayPolyManager
 
 LIGHT_FILTER = pymunk.ShapeFilter(
     mask=pymunk.ShapeFilter.ALL_MASKS ^ (
@@ -102,7 +102,9 @@ class BaseLight(object):
         self.angle_limits = angle_limits
         self.body = pymunk.Body(0, 0, pymunk.body.Body.STATIC)
         self.fitting = pymunk.Circle(self.body, 10.0, self.position)
+        self.fitting.filter = FITTINGS_FILTER
         self.body.light = self
+        self.ray_manager = RayPolyManager(self.body, LIGHT_FILTER)
 
     @classmethod
     def load(cls, config):
@@ -116,12 +118,9 @@ class BaseLight(object):
     def add(self, space):
         if self.body.space is not None:
             space.remove(self.body, *self.body.shapes)
-        shapes = self.shapes_for_ray_polys(
-            calculate_ray_polys(space, self.body, self.position, LIGHT_FILTER))
-        for shape in shapes:
-            shape.filter = LIGHT_FILTER
-        self.fitting.filter = FITTINGS_FILTER
-        space.add(self.body, self.fitting, *shapes)
+        self.ray_manager.generate_rays(space, self.position)
+        ray_shapes = self.ray_manager.polys()
+        space.add(self.body, self.fitting, *ray_shapes)
 
     def shapes_for_ray_polys(self, ray_polys):
         return ray_polys
index 1892edf4febe9e97dd9e26806afed426780c4e9c..d6d0a695db90556a29f98ffc958798aac5e8c2a8 100644 (file)
@@ -1,6 +1,7 @@
 """ Light ray manipulation. Pew. Pew. Pew. Wommmm. """
 
 import pymunk
+import pymunk.autogeometry
 import pymunk.pygame_util
 
 from .constants import SCREEN_SIZE
@@ -25,26 +26,55 @@ def screen_rays(pos):
         yield pymunk.Vec2d(x, bottom)
 
 
-@debug_timer("rays.calculate_ray_polys")
-def calculate_ray_polys(space, body, position, light_filter):
+@debug_timer("rays.calculate_ray_polys", True)
+def calculate_ray_polys(space, position, light_filter):
     position = pymunk.Vec2d(position)
     vertices = [position]
+    start, end = None, None
     ray_polys = []
     for ray in screen_rays(position):
         info = space.segment_query_first(position, ray, 1, light_filter)
         point = ray if info is None else info.point
         vertices.append(point)
-        if len(vertices) > 3:
+        if len(vertices) == 2:
+            start = vertices[1]
+        elif len(vertices) > 3:
             trial_poly = pymunk.Poly(None, vertices)
             trial_poly.update(pymunk.Transform.identity())
-            query_prev = trial_poly.point_query(vertices[-2])
+            query_prev = trial_poly.point_query(end)
             query_pos = trial_poly.point_query(position)
             if query_prev.distance < -0.01 or query_pos.distance < -0.01:
-                new_poly = pymunk.Poly(body, vertices[:-1])
-                vertices = [position, vertices[-1]]
-                ray_polys.append(new_poly)
+                ray_polys.append(RayPoly(start, end, vertices[:-1]))
+                start = vertices[-1]
+                vertices = [position, start]
             else:
-                vertices = trial_poly.get_vertices() + [point]
+                vertices = trial_poly.get_vertices()
+        end = point
     if len(vertices) > 2:
-        ray_polys.append(pymunk.Poly(body, vertices))
+        ray_polys.append(RayPoly(start, end, vertices))
     return ray_polys
+
+
+class RayPolyManager(object):
+    def __init__(self, body, ray_filter):
+        self._body = body
+        self._ray_filter = ray_filter
+        self._rays = []
+
+    def generate_rays(self, space, position):
+        self._rays = calculate_ray_polys(space, position, self._ray_filter)
+
+    def polys(self):
+        return [rp.poly(self._body, self._ray_filter) for rp in self._rays]
+
+
+class RayPoly(object):
+    def __init__(self, start, end, vertices):
+        self.start = start
+        self.end = end
+        self.vertices = vertices
+
+    def poly(self, body, filter):
+        shape = pymunk.Poly(body, self.vertices)
+        shape.filter = filter
+        return shape