Merge branch 'master' of ctpug.org.za:tabakrolletjie
[tabakrolletjie.git] / tabakrolletjie / rays.py
1 """ Light ray manipulation. Pew. Pew. Pew. Wommmm. """
2
3 import pymunk
4 import pymunk.pygame_util
5
6 from .constants import SCREEN_SIZE
7 from .utils import debug_timer
8
9
10 def screen_rays(pos):
11     """ An iterable that returns ordered rays from pos to the edge of the
12         screen, starting with the edge point (0, 0) and continuing clockwise
13         in pymunk coordinates.
14     """
15     w, h = SCREEN_SIZE
16     left, right, bottom, top = 0, w, 0, h
17     step = 1
18     for y in range(0, h, step):
19         yield pymunk.Vec2d(left, y)
20     for x in range(0, w, step):
21         yield pymunk.Vec2d(x, top)
22     for y in range(top, -1, -step):
23         yield pymunk.Vec2d(right, y)
24     for x in range(right, -1, -step):
25         yield pymunk.Vec2d(x, bottom)
26
27
28 @debug_timer("rays.calculate_ray_polys")
29 def calculate_ray_polys(space, body, position, light_filter):
30     position = pymunk.Vec2d(position)
31     vertices = [position]
32     ray_polys = []
33     for ray in screen_rays(position):
34         info = space.segment_query_first(position, ray, 1, light_filter)
35         point = ray if info is None else info.point
36         vertices.append(point)
37         if len(vertices) > 3:
38             trial_poly = pymunk.Poly(None, vertices)
39             trial_poly.update(pymunk.Transform.identity())
40             query_prev = trial_poly.point_query(vertices[-2])
41             query_pos = trial_poly.point_query(position)
42             if query_prev.distance < -0.01 or query_pos.distance < -0.01:
43                 new_poly = pymunk.Poly(body, vertices[:-1])
44                 vertices = [position, vertices[-1]]
45                 ray_polys.append(new_poly)
46             else:
47                 vertices = trial_poly.get_vertices() + [point]
48     if len(vertices) > 2:
49         ray_polys.append(pymunk.Poly(body, vertices))
50     return ray_polys