7b26fed214ebb600a5366aa4d40c85b1eb6edcee
[tabakrolletjie.git] / tabakrolletjie / enemies.py
1 # Boyd, the friendly, misunderstood turnip loving, light hating space mould
2
3 import random
4
5 import pymunk
6 import pymunk.pygame_util
7 import pygame.draw
8 import pygame.surface
9 import pygame.display
10
11 import pygame.locals as pgl
12
13 from .constants import SCREEN_SIZE, MOULD_CATEGORY, OBSTACLE_CATEGORY
14 from .loader import loader
15
16 MOULD_FILTER = pymunk.ShapeFilter(
17     mask=MOULD_CATEGORY | OBSTACLE_CATEGORY,
18     categories=MOULD_CATEGORY)
19
20
21 class Mould(pymunk.Body):
22     """A segment of Boyd"""
23
24     def __init__(self, gamestate, space, pos):
25         super(Mould, self).__init__(0, 0, pymunk.Body.STATIC)
26         self.position = pos
27         self._shape = pymunk.Circle(self, 16)
28         space.add(self, self._shape)
29         self._shape.filter = MOULD_FILTER
30         self._resistances = {}
31         self._age = 0
32         self._img = None
33
34     def get_image(self):
35         if not self._img:
36             name = random.choice(
37                 ('mouldA.png', 'mouldB.png', 'mouldC.png'))
38             self._img = loader.load_image("32", name)
39         return self._img
40
41     def tick(self, gamestate, space, moulds):
42         """Grow and / or Die"""
43         self._age += 1
44
45         refresh = False
46
47         if (self._age % 15) == 0 and len(moulds) < 1000:
48             # Spawn a new child, if we can
49             spawn = True
50             choice = random.randint(0, 4)
51             if choice == 0:
52                 pos = self.position + (0, 24)
53             elif choice == 1:
54                 pos = self.position + (24, 0)
55             elif choice == 2:
56                 pos = self.position + (-24, 0)
57             else:
58                 pos = self.position + (0, -24)
59             # check for bounds
60             if pos[0] < 0 or pos[0] >= SCREEN_SIZE[0]:
61                 spawn = False
62             if pos[1] < 0 or pos[1] >= SCREEN_SIZE[1]:
63                 spawn = False
64             # Check for free space
65             # We allow some overlap, hence not checking full radius
66             query = space.point_query(pos, 8, MOULD_FILTER)
67             if query:
68                 # for x in query:
69                 #     if not isinstance(x.shape.body, Mould):
70                 #         print x.shape, x.shape.body
71                 spawn = False
72             if spawn:
73                 child = Mould(gamestate, space, pos)
74                 moulds.append(child)
75                 refresh = True
76
77         if self._age > 120:
78             # We die of old age
79             space.remove(self, self._shape)
80             moulds.remove(self)
81             refresh = True
82         return refresh
83
84     def damage(self, light_color, intensity):
85         """Take damage for light, adjusted for resistances."""
86
87
88 class Boyd(object):
89
90     def __init__(self, gamestate, space):
91         seed = Mould(gamestate, space, (400, 400))
92         self._moulds = [seed]
93         self._image = pygame.surface.Surface(SCREEN_SIZE)
94         self._image.convert_alpha(pygame.display.get_surface())
95         self._image.fill((0, 0, 0, 0))
96
97     def tick(self, gamestate, space):
98         redraw = False
99         for mould in self._moulds[:]:
100             if mould.tick(gamestate, space, self._moulds):
101                 redraw = True
102         if redraw:
103             self._image.fill((0, 0, 0, 0))
104             for mould in self._moulds:
105                 pos = pymunk.pygame_util.to_pygame(mould.position, self._image)
106                 self._image.blit(mould.get_image(), pos, None,
107                                  pgl.BLEND_RGBA_ADD)
108
109     def render(self, surface):
110         """Draw ourselves"""
111         surface.blit(self._image, (0, 0), None, pgl.BLEND_RGBA_ADD)