From: Simon Cross Date: Wed, 7 Sep 2016 19:12:07 +0000 (+0200) Subject: Move ray manipulation into a separate module. X-Git-Tag: tabakrolletjie-v1.0.0~201 X-Git-Url: https://git.ctpug.org.za/?p=tabakrolletjie.git;a=commitdiff_plain;h=3c1acdcd43a2d901ae165e2a278c5ed31ebca4dd Move ray manipulation into a separate module. --- diff --git a/tabakrolletjie/lights.py b/tabakrolletjie/lights.py index 285ca2e..097abd2 100644 --- a/tabakrolletjie/lights.py +++ b/tabakrolletjie/lights.py @@ -7,9 +7,8 @@ import pygame.display import pygame.draw import pygame.locals as pgl -from .constants import ( - SCREEN_SIZE, LIGHT_CATEGORY, FITTINGS_CATEGORY) -from .utils import debug_timer +from .constants import LIGHT_CATEGORY, FITTINGS_CATEGORY +from .rays import calculate_ray_polys LIGHT_FILTER = pymunk.ShapeFilter( mask=pymunk.ShapeFilter.ALL_MASKS ^ ( @@ -25,49 +24,6 @@ FITTINGS_FILTER = pymunk.ShapeFilter( LIT_BY_FILTER = pymunk.ShapeFilter(mask=LIGHT_CATEGORY) -def screen_rays(pos): - """ 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 - step = 1 - for y in range(0, h, step): - yield pymunk.Vec2d(left, y) - for x in range(0, w, step): - yield pymunk.Vec2d(x, top) - for y in range(top, -1, -step): - yield pymunk.Vec2d(right, y) - for x in range(right, -1, -step): - yield pymunk.Vec2d(x, bottom) - - -@debug_timer("lights.calculate_ray_polys") -def calculate_ray_polys(space, body, position): - position = pymunk.Vec2d(position) - vertices = [position] - 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: - trial_poly = pymunk.Poly(None, vertices) - trial_poly.update(pymunk.Transform.identity()) - query_prev = trial_poly.point_query(vertices[-2]) - 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) - else: - vertices = trial_poly.get_vertices() + [point] - if len(vertices) > 2: - ray_polys.append(pymunk.Poly(body, vertices)) - return ray_polys - - class LightManager(object): """ Manages a set of lights. """ @@ -161,7 +117,7 @@ class BaseLight(object): 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)) + calculate_ray_polys(space, self.body, self.position, LIGHT_FILTER)) for shape in shapes: shape.filter = LIGHT_FILTER self.fitting.filter = FITTINGS_FILTER diff --git a/tabakrolletjie/rays.py b/tabakrolletjie/rays.py new file mode 100644 index 0000000..1892edf --- /dev/null +++ b/tabakrolletjie/rays.py @@ -0,0 +1,50 @@ +""" Light ray manipulation. Pew. Pew. Pew. Wommmm. """ + +import pymunk +import pymunk.pygame_util + +from .constants import SCREEN_SIZE +from .utils import debug_timer + + +def screen_rays(pos): + """ 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 + step = 1 + for y in range(0, h, step): + yield pymunk.Vec2d(left, y) + for x in range(0, w, step): + yield pymunk.Vec2d(x, top) + for y in range(top, -1, -step): + yield pymunk.Vec2d(right, y) + for x in range(right, -1, -step): + yield pymunk.Vec2d(x, bottom) + + +@debug_timer("rays.calculate_ray_polys") +def calculate_ray_polys(space, body, position, light_filter): + position = pymunk.Vec2d(position) + vertices = [position] + 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: + trial_poly = pymunk.Poly(None, vertices) + trial_poly.update(pymunk.Transform.identity()) + query_prev = trial_poly.point_query(vertices[-2]) + 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) + else: + vertices = trial_poly.get_vertices() + [point] + if len(vertices) > 2: + ray_polys.append(pymunk.Poly(body, vertices)) + return ray_polys