Merge branch 'master' of ctpug.org.za:tabakrolletjie
authorSimon Cross <hodgestar@gmail.com>
Sat, 10 Sep 2016 20:07:54 +0000 (22:07 +0200)
committerSimon Cross <hodgestar@gmail.com>
Sat, 10 Sep 2016 20:07:54 +0000 (22:07 +0200)
tabakrolletjie/lights.py
tabakrolletjie/rays.py

index 498c0b09c644c5de9bda9a2be4a3dabfb7c7a7ef..747ce92e86449ea92102dbbb5b0d73465339dd66 100644 (file)
@@ -146,7 +146,8 @@ class BaseLight(object):
 
     def __init__(
             self, colours, position, intensity=1.0, radius_limits=None,
-            direction=None, spread=None, on=True, start_colour=None):
+            direction=None, spread=None, on=True, start_colour=None,
+            bounding_radius=None):
         self.colour_cycle = colours
         self.colour_pos = 0
         self.colour = colours[0]
@@ -161,7 +162,8 @@ class BaseLight(object):
         self.body.light = self
         self.ray_manager = self.RAY_MANAGER(
             self.body, position, ray_filter=LIGHT_FILTER,
-            radius_limits=radius_limits, direction=direction, spread=spread)
+            radius_limits=radius_limits, direction=direction, spread=spread,
+            bounding_radius=bounding_radius)
         self.fitting = pymunk.Circle(
             self.body, self.FITTING_RADIUS, self.ray_manager.position)
         self.fitting.filter = FITTINGS_FILTER
@@ -320,7 +322,8 @@ class PulsatingLamp(BaseLight):
             "intensity_range", self.DEFAULT_INTENSITY_RANGE)
         self.intensity_velocity = kw.pop(
             "intensity_velocity", self.DEFAULT_INTENSITY_VELOCITY)
-        super(PulsatingLamp, self).__init__(**kw)
+        super(PulsatingLamp, self).__init__(
+            bounding_radius=self.pulse_range[1], **kw)
 
     def serialize(self):
         result = super(PulsatingLamp, self).serialize()
index 8b532784a46a80e97f354cb9686b6161fe2bbe8b..7d880d0aaa5ea417e38cb08fcfe167c5732c42f2 100644 (file)
@@ -8,30 +8,30 @@ import pymunk
 import pymunk.autogeometry
 import pymunk.pygame_util
 
-from .constants import SCREEN_SIZE
 from .utils import debug_timer
 
 
-def screen_rays():
+def screen_rays(pos, bounding_radius):
     """ An iterable that returns ordered rays from pos to the edge of the
         screen, starting with the edge point (0, 0) and continuing clockwise
         in pymunk coordinates.
     """
-    w, h = SCREEN_SIZE
-    left, right, bottom, top = 0, w, 0, h
+    r = int(bounding_radius)
+    left, right = int(pos.x) - r, int(pos.x) + r
+    bottom, top = int(pos.y) + r, int(pos.y) - r
     step = 1
-    for y in range(0, h, step):
+    for y in range(top, bottom + 1, step):
         yield pymunk.Vec2d(left, y)
-    for x in range(0, w, step):
+    for x in range(left, right + 1, step):
         yield pymunk.Vec2d(x, top)
-    for y in range(top, -1, -step):
+    for y in range(bottom, top - 1, -step):
         yield pymunk.Vec2d(right, y)
-    for x in range(right, -1, -step):
+    for x in range(right, left - 1, -step):
         yield pymunk.Vec2d(x, bottom)
 
 
 @debug_timer("rays.calculate_ray_polys")
-def calculate_ray_polys(space, position, light_filter):
+def calculate_ray_polys(space, position, bounding_radius, light_filter):
     """ Calculate a set of convex RayPolys that cover all the areas that light
         can reach from the given position, taking into account the obstacles
         present in the space.
@@ -40,7 +40,7 @@ def calculate_ray_polys(space, position, light_filter):
     vertices = [position]
     start, end = None, None
     ray_polys = []
-    for ray in screen_rays():
+    for ray in screen_rays(position, bounding_radius):
         info = space.segment_query_first(position, ray, 1, light_filter)
         point = ray if info is None else info.point
         vertices.append(point)
@@ -79,7 +79,7 @@ def to_pymunk_radians(deg):
 class RayPolyManager(object):
     def __init__(
             self, body, position, ray_filter, radius_limits, direction,
-            spread):
+            spread, bounding_radius):
         self._body = body  # light's body
         self._position = pymunk.Vec2d(position)  # light's position
         self._ray_filter = ray_filter  # light filter
@@ -88,11 +88,13 @@ class RayPolyManager(object):
         self._start = None  # normal vector in direction of start angle limit
         self._end = None  # normal vector in direction of end angle limit
         self._set_angle_limits(direction, spread)
+        self._bounding_radius = None   # absolute maximum radius
         if direction:
             self.direction = direction  # Update direction
         self._max_radius = None  # maximum radius in pixels
         self._min_radius = None  # minimum radius in pixels
         self._set_radius_limits(radius_limits)
+        self._set_bounding_radius(bounding_radius)
         self._old_poly_cache = None  # last polys added to the space
         self._poly_cache = None  # list of pymunk.Polys for rays
         self._space = None  # space the rays form part of
@@ -100,7 +102,8 @@ class RayPolyManager(object):
     def set_space(self, space):
         self._space = space
         self._rays = calculate_ray_polys(
-            self._space, self._position, self._ray_filter)
+            self._space, self._position, self._bounding_radius,
+            self._ray_filter)
         self._poly_cache = None
 
     def update_shapes(self):
@@ -157,6 +160,11 @@ class RayPolyManager(object):
         else:
             self._max_radius = radius_limits[1]
 
+    def _set_bounding_radius(self, bounding_radius):
+        if bounding_radius is None:
+            bounding_radius = self._max_radius
+        self._bounding_radius = bounding_radius
+
     def rotatable(self):
         return self._direction is not None