From 1f2682e60071bce98ded8f52747a3742e056d272 Mon Sep 17 00:00:00 2001 From: Simon Cross Date: Wed, 7 Sep 2016 22:02:02 +0200 Subject: [PATCH] Factor out ray manager. --- tabakrolletjie/lights.py | 13 +++++------ tabakrolletjie/rays.py | 48 ++++++++++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/tabakrolletjie/lights.py b/tabakrolletjie/lights.py index 097abd2..39b1815 100644 --- a/tabakrolletjie/lights.py +++ b/tabakrolletjie/lights.py @@ -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 diff --git a/tabakrolletjie/rays.py b/tabakrolletjie/rays.py index 1892edf..d6d0a69 100644 --- a/tabakrolletjie/rays.py +++ b/tabakrolletjie/rays.py @@ -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 -- 2.34.1