Remove unused pos arg.
[tabakrolletjie.git] / tabakrolletjie / rays.py
index f4c5ed16fcc69f1500aab6f6be3e0eeadb77e2a6..a475d8fb27bb6c680a90555cad7dc2a4f6043954 100644 (file)
@@ -2,6 +2,8 @@
 
 import math
 
 
 import math
 
+import pygame.rect
+
 import pymunk
 import pymunk.autogeometry
 import pymunk.pygame_util
 import pymunk
 import pymunk.autogeometry
 import pymunk.pygame_util
@@ -10,7 +12,7 @@ from .constants import SCREEN_SIZE
 from .utils import debug_timer
 
 
 from .utils import debug_timer
 
 
-def screen_rays(pos):
+def screen_rays():
     """ 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.
     """ 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.
@@ -38,7 +40,7 @@ def calculate_ray_polys(space, position, light_filter):
     vertices = [position]
     start, end = None, None
     ray_polys = []
     vertices = [position]
     start, end = None, None
     ray_polys = []
-    for ray in screen_rays(position):
+    for ray in screen_rays():
         info = space.segment_query_first(position, ray, 1, light_filter)
         point = ray if info is None else info.point
         vertices.append(point)
         info = space.segment_query_first(position, ray, 1, light_filter)
         point = ray if info is None else info.point
         vertices.append(point)
@@ -75,27 +77,104 @@ def to_pymunk_radians(deg):
 
 
 class RayPolyManager(object):
 
 
 class RayPolyManager(object):
-    def __init__(self, body, ray_filter):
+    def __init__(
+            self, body, position, ray_filter, radius_limits, direction,
+            spread):
         self._body = body  # light's body
         self._body = body  # light's body
+        self._position = pymunk.Vec2d(position)  # light's position
         self._ray_filter = ray_filter  # light filter
         self._rays = []  # list of RayPolys
         self._ray_filter = ray_filter  # light filter
         self._rays = []  # list of RayPolys
+        self._direction = None  # normal vector for direction
         self._start = None  # normal vector in direction of start angle limit
         self._end = None  # normal vector in direction of end angle limit
         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)
+        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._old_poly_cache = None  # last polys added to the space
         self._poly_cache = None  # list of pymunk.Polys for rays
         self._poly_cache = None  # list of pymunk.Polys for rays
+        self._space = None  # space the rays form part of
 
 
-    def generate_rays(self, space, position):
-        self._rays = calculate_ray_polys(space, position, self._ray_filter)
+    def set_space(self, space):
+        self._space = space
+        self._rays = calculate_ray_polys(
+            self._space, self._position, self._ray_filter)
         self._poly_cache = None
 
         self._poly_cache = None
 
-    def set_angle_limits(self, angle_limits):
-        if angle_limits is None:
+    def update_shapes(self):
+        if self._old_poly_cache:
+            self._space.remove(*self._old_poly_cache)
+        new_polys = self._old_poly_cache = self.polys()
+        self._space.add(*new_polys)
+
+    @property
+    def position(self):
+        return self._position
+
+    @property
+    def max_radius(self):
+        return self._max_radius
+
+    @max_radius.setter
+    def max_radius(self, value):
+        self._max_radius = value or 0.0
+
+    @property
+    def min_radius(self):
+        return self._min_radius
+
+    @min_radius.setter
+    def min_radius(self, value):
+        self._min_radius = value or 0.0
+
+    def reaches(self, position):
+        distance = self.position.get_distance(position)
+        return (self._min_radius <= distance <= self._max_radius)
+
+    def _set_radius_limits(self, radius_limits):
+        if radius_limits is None or not radius_limits[0]:
+            self._min_radius = 0
+        else:
+            self._min_radius = radius_limits[0]
+        if radius_limits is None or not radius_limits[1]:
+            self._max_radius = 50.0
+        else:
+            self._max_radius = radius_limits[1]
+
+    def rotatable(self):
+        return self._direction is not None
+
+    @property
+    def direction(self):
+        if self._direction is None:
+            return 0
+        return self._direction.angle_degrees
+
+    @direction.setter
+    def direction(self, degrees):
+        spread = self._direction.get_angle_between(self._start)
+        self._direction.angle_degrees = degrees
+        self._start = self._direction.rotated(spread)
+        self._end = self._direction.rotated(-spread)
+        self._poly_cache = None
+
+    @property
+    def spread(self):
+        if not self._direction:
+            return 2 * math.pi
+        return math.fabs(self._start.get_angle_between(self._end))
+
+    def _set_angle_limits(self, direction, spread):
+        if direction is None or spread is None:
+            self._direction = None
             self._start = None
             self._end = None
         else:
             self._start = None
             self._end = None
         else:
-            self._start = pymunk.Vec2d(1, 0).rotated(
-                to_pymunk_radians(angle_limits[0]))
-            self._end = pymunk.Vec2d(1, 0).rotated(
-                to_pymunk_radians(angle_limits[1]))
+            self._direction = pymunk.Vec2d(1, 0)
+            self._start = self._direction.rotated_degrees(-spread/2.)
+            self._end = self._direction.rotated_degrees(spread/2.)
         self._poly_cache = None
 
     def polys(self):
         self._poly_cache = None
 
     def polys(self):
@@ -109,6 +188,17 @@ class RayPolyManager(object):
                     poly_cache.append(poly)
         return self._poly_cache
 
                     poly_cache.append(poly)
         return self._poly_cache
 
+    def pygame_position(self, surface):
+        return pymunk.pygame_util.to_pygame(self._position, surface)
+
+    def pygame_rect(self, surface):
+        half_width = self.max_radius
+        rect_width = half_width * 2
+        rect_x, rect_y = pymunk.pygame_util.to_pygame(self._position, surface)
+        dest_rect = pygame.rect.Rect(rect_x, rect_y, rect_width, rect_width)
+        dest_rect.move_ip(-half_width, -half_width)
+        return dest_rect
+
     def pygame_polys(self, surface):
         return [
             [pymunk.pygame_util.to_pygame(v, surface)
     def pygame_polys(self, surface):
         return [
             [pymunk.pygame_util.to_pygame(v, surface)
@@ -135,9 +225,9 @@ class RayPoly(object):
             return trial  # no limits
 
         start_info = trial.segment_query(
             return trial  # no limits
 
         start_info = trial.segment_query(
-            self.position + 0.1 * start, self.position + 1250 * start, 0)
+            self.position + 1250 * start, self.position + 0.1 * start, 0)
         end_info = trial.segment_query(
         end_info = trial.segment_query(
-            self.position + 0.1 * end, self.position + 1250 * end, 0)
+            self.position + 1250 * end, self.position + 0.1 * end, 0)
 
         vertices = self.vertices[:]
         vertices = [
 
         vertices = self.vertices[:]
         vertices = [