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 ^ (
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):
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
""" Light ray manipulation. Pew. Pew. Pew. Wommmm. """
import pymunk
+import pymunk.autogeometry
import pymunk.pygame_util
from .constants import SCREEN_SIZE
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