From: Simon Cross Date: Sun, 4 Sep 2016 20:40:39 +0000 (+0200) Subject: First working version of light rays. X-Git-Tag: tabakrolletjie-v1.0.0~246 X-Git-Url: https://git.ctpug.org.za/?a=commitdiff_plain;h=e01ef513c433374cdab9069363f6d27a33a15143;p=tabakrolletjie.git First working version of light rays. --- diff --git a/tabakrolletjie/lights.py b/tabakrolletjie/lights.py index 81740d8..ef84879 100644 --- a/tabakrolletjie/lights.py +++ b/tabakrolletjie/lights.py @@ -4,6 +4,53 @@ import pymunk import pymunk.pygame_util import pygame.draw +import pygame.locals as pgl + +from .constants import SCREEN_SIZE, LIGHT_CATEGORY + +LIGHT_FILTER = pymunk.ShapeFilter( + mask=pymunk.ShapeFilter.ALL_MASKS ^ LIGHT_CATEGORY, + categories=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 + for y in range(h): + yield pymunk.Vec2d(left, y) + for x in range(w): + yield pymunk.Vec2d(x, top) + for y in range(top, -1, -1): + yield pymunk.Vec2d(right, y) + for x in range(right, -1, -1): + yield pymunk.Vec2d(x, bottom) + + +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) + if len(vertices) > 2: + ray_polys.append(pymunk.Poly(body, vertices)) + print "NUM POLYS: ", len(ray_polys) + return ray_polys class BaseLight(object): @@ -17,10 +64,13 @@ class BaseLight(object): def add(self, space): if self.body.space is not None: space.remove(self.body, *self.body.shapes) - shapes = self.determine_ray_polys(space) + shapes = self.shapes_for_ray_polys( + calculate_ray_polys(space, self.body, self.position)) + for shape in shapes: + shape.filter = LIGHT_FILTER space.add(self.body, *shapes) - def determine_ray_polys(self, space): + def shapes_for_ray_polys(self, space): raise NotImplementedError( "Lights should implement .determine_ray_polys.") @@ -40,18 +90,28 @@ class SpotLight(BaseLight): super(SpotLight, self).__init__(colour, position) self.direction = direction self.spread = spread + self.i = 0 - def determine_ray_polys(self, space): + def shapes_for_ray_polys(self, ray_polys): x, y = self.position - return [pymunk.Poly(self.body, [ - self.position, [x + 50, y], [x, y + 50]])] + return ray_polys #+ [ + # pymunk.Poly(self.body, [self.position, [x + 50, y], [x, y + 50]])] def render(self, surface): + subsurface = surface.copy() + pygame.draw.circle( + surface, (255, 255, 0), + pymunk.pygame_util.to_pygame(self.position, surface), 5) for shape in self.body.shapes: pygame_poly = [ pymunk.pygame_util.to_pygame(v, surface) for v in shape.get_vertices()] - pygame.draw.polygon(surface, (255, 255, 255), pygame_poly) + pygame.draw.polygon( + subsurface, (200, 200, 200), pygame_poly, 0) + pygame.draw.aalines( + subsurface, (200, 200, 200), True, pygame_poly, 1) + subsurface.set_alpha(200) + surface.blit(subsurface, (0, 0), None) class Lamp(BaseLight):