X-Git-Url: https://git.ctpug.org.za/?a=blobdiff_plain;f=tabakrolletjie%2Flights.py;h=84318d15e253616dbe529fcd5a0f0d869e8a1ad2;hb=1a207c0ab976690b60d2a61fa95ff7990f214de1;hp=285ca2e98def1226e0599335c8b2284995400e3b;hpb=a15034f0ef18afe83862838c5de0de3b7d5a86cd;p=tabakrolletjie.git diff --git a/tabakrolletjie/lights.py b/tabakrolletjie/lights.py index 285ca2e..84318d1 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 RayPolyManager 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. """ @@ -120,6 +76,10 @@ class LightManager(object): for light in self._lights: light.render_fitting(surface) + def tick(self): + for light in self._lights: + light.tick() + class BaseLight(object): """ Common light functionality. """ @@ -137,7 +97,7 @@ class BaseLight(object): def __init__( self, colour, position, intensity=1.0, - radius_limits=(None, None), angle_limits=(None, None)): + radius_limits=(None, None), angle_limits=None): self.colour = colour self.position = pymunk.Vec2d(position) self.on = True @@ -146,7 +106,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): @@ -160,12 +122,10 @@ 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)) - 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) + self.ray_manager.set_angle_limits(self.angle_limits) + 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 @@ -200,12 +160,7 @@ class BaseLight(object): white, black = (255, 255, 255), (0, 0, 0) ray_mask.fill(black) - for shape in self.body.shapes: - if shape is self.fitting: - continue - pygame_poly = [ - pymunk.pygame_util.to_pygame(v, surface) for v in - shape.get_vertices()] + for pygame_poly in self.ray_manager.pygame_polys(surface): pygame.draw.polygon(ray_mask, white, pygame_poly, 0) pygame.draw.aalines(ray_mask, white, True, pygame_poly, 1) @@ -238,9 +193,21 @@ class BaseLight(object): pymunk.pygame_util.to_pygame(self.fitting.offset, surface), int(self.fitting.radius)) + def tick(self): + pass + class SpotLight(BaseLight): def __init__(self, **kw): kw.pop("direction", None) kw.pop("spread", None) + self.angular_velocity = kw.pop("angular_velocity", None) super(SpotLight, self).__init__(**kw) + + def tick(self): + if self.angular_velocity: + start, end = self.angle_limits + start = (start + self.angular_velocity) % 360.0 + end = (end + self.angular_velocity) % 360.0 + self.angle_limits = (start, end) + self.ray_manager.set_angle_limits(self.angle_limits)