Ensure color_pos is always -1 when the lights go out, so behaviour is always consistent
[tabakrolletjie.git] / tabakrolletjie / obstacles.py
1 """ Obstacles for light and space mould. """
2
3 import pygame.locals as pgl
4
5 import pymunk
6 import pymunk.pygame_util
7 import pygame.draw
8 import pygame.surface
9
10 from .constants import (SCREEN_SIZE, OBSTACLE_CATEGORY)
11 from .loader import loader
12
13 OBSTACLE_FILTER = pymunk.ShapeFilter(categories=OBSTACLE_CATEGORY)
14
15
16 class ObstacleManager(object):
17     """ Manages a set of obstacles. """
18
19     def __init__(self, space, gamestate):
20         self._space = space
21         self._obstacles = [
22             BaseObstacle.load(cfg) for cfg in gamestate.station["obstacles"]]
23         for obs in self._obstacles:
24             obs.add(self._space)
25
26     def render(self, surface):
27         for obs in self._obstacles:
28             obs.render(surface)
29
30
31 class BaseObstacle(object):
32     def __init__(self):
33         self.body = pymunk.Body(0, 0, pymunk.body.Body.STATIC)
34         self.shapes = []
35
36     def add(self, space):
37         if self.body.space is not None:
38             space.remove(self.body, *self.body.shapes)
39         for shape in self.shapes:
40             shape.filter = OBSTACLE_FILTER
41         space.add(self.body, *self.shapes)
42
43     def render(self, surface):
44         raise NotImplementedError("Obstacles should implement .render().")
45
46     @classmethod
47     def load(cls, config):
48         kw = config.copy()
49         obstacle_type = kw.pop("type")
50         [obstacle_class] = [
51             c for c in cls.__subclasses__()
52             if c.__name__.lower() == obstacle_type]
53         return obstacle_class(**kw)
54
55
56 class Wall(BaseObstacle):
57
58     def __init__(self, vertices):
59         super(Wall, self).__init__()
60         self.shapes.append(pymunk.Poly(self.body, vertices))
61         self._image = None
62
63     def get_image(self):
64         if self._image is None:
65             self._image = pygame.surface.Surface(SCREEN_SIZE).convert_alpha()
66             self._image.fill((0, 0, 0, 0))
67
68             for shape in self.shapes:
69                 pygame_poly = [
70                     pymunk.pygame_util.to_pygame(v, self._image) for v in
71                     shape.get_vertices()]
72                 pygame.draw.polygon(self._image, (255, 255, 255), pygame_poly)
73
74             wall_texture = loader.load_image(
75                 "textures", "stone.png").convert_alpha()
76             self._image.blit(wall_texture, (0, 0), None, pgl.BLEND_RGBA_MULT)
77
78         return self._image
79
80     def render(self, surface):
81         surface.blit(self.get_image(), (0, 0), None, 0)
82
83
84 class Shrub(BaseObstacle):
85
86     def __init__(self, shrublets):
87         super(Shrub, self).__init__()
88         for (x, y, r) in shrublets:
89             vec = pymunk.Vec2d(0, int(r))
90             STEPS = 18
91             vertices = [
92                 vec.rotated_degrees(angle) + (x, y)
93                 for angle in range(0, 360, 360/STEPS)]
94             vertices = [(v.x, v.y) for v in vertices]
95
96             self.shapes.append(pymunk.Poly(self.body, vertices))
97         self.shrublets = shrublets
98         self._image = None
99
100     def get_image(self):
101         if self._image is None:
102             self._image = pygame.surface.Surface(SCREEN_SIZE).convert_alpha()
103             self._image.fill((0, 0, 0, 0))
104
105             for (x, y, r) in self.shrublets:
106                 centre = pymunk.pygame_util.to_pygame((x, y), self._image)
107                 pygame.draw.circle(self._image, (255, 255, 255), centre, r)
108
109             shrub_texture = loader.load_image(
110                 "textures", "shrub.png").convert_alpha()
111             self._image.blit(shrub_texture, (0, 0), None, pgl.BLEND_RGBA_MULT)
112
113         return self._image
114
115     def render(self, surface):
116         surface.blit(self.get_image(), (0, 0), None, 0)