The endless pointlessness of level progression
[koperkapel.git] / koperkapel / gamelib / tiles.py
1 """ Definitions for the various tile types """
2
3 import os
4 import random
5
6 from pygame.transform import rotate
7
8 from pgzero.loaders import images
9
10
11 class Tile:
12     IMG = None
13     TILESET = None
14
15     @classmethod
16     def image(cls, neighbors):
17         if cls.IMG is None or cls.TILESET is None:
18             raise NotImplementedError()
19         return images.load(os.path.join(cls.TILESET, cls.IMG))
20
21 class OrientatedTile(Tile):
22     ANGLE = None
23
24     @classmethod
25     def image(cls, neighbors):
26         if cls.IMG is None or cls.TILESET is None:
27             raise NotImplementedError()
28         img = images.load(os.path.join(cls.TILESET, cls.IMG))
29         if cls.ANGLE:
30             img = rotate(img, cls.ANGLE)
31         return img
32
33
34 class RandomizedTile(Tile):
35     IMGDIR = None
36     TILESET = None
37     ROTATE = True
38
39     @classmethod
40     def image(cls, neighbors):
41         if cls.IMGDIR is None or cls.TILESET is None:
42             raise NotImplementedError()
43
44         imgdir = os.path.join(os.path.dirname(__file__), '..', 'images',
45                 cls.TILESET, cls.IMGDIR)
46         imgpath = os.path.splitext(random.choice(os.listdir(imgdir)))[0]
47         img = images.load(os.path.join(cls.TILESET, cls.IMGDIR, imgpath))
48
49         if cls.ROTATE:
50             img = rotate(img, 90 * random.randint(0, 3))
51
52         return img
53
54 class Floor(RandomizedTile):
55     IMGDIR = "floor"
56
57 class Wall(RandomizedTile):
58     IMGDIR = "wall"
59
60 class Underground(RandomizedTile):
61     IMGDIR = "underground"
62
63 class Grate(Tile):
64     IMG = os.path.join('grate', 'grate')
65     TILESET = 'bunker'
66
67
68 class Exit(Tile):
69     IMG = os.path.join('exit', 'exit')
70     TILESET = 'bunker'
71
72
73 class Tunnel(OrientatedTile):
74
75     @classmethod
76     def image(cls, neighbors):
77         connections = [True if 'crawl' in x['behaviour'] else False for x in neighbors]
78         conn_count = connections.count(True)
79         # simple cases
80         cls.ANGLE = 0
81         if conn_count == 0:
82             # return single point tunnel
83             cls.IMG = os.path.join('tunnel', 'tunnel_none')
84         elif conn_count == 4:
85             # crossroads
86             cls.IMG = os.path.join('tunnel', 'tunnel_crossroads')
87         elif conn_count == 1:
88             # 1 point connector, roatated correctly
89             cls.IMG = os.path.join('tunnel', 'tunnel_1way')
90             # because of the ordering of neighbors, we use this formulation
91             for x, angle in zip(connections, (90, 270, 0, 180)):
92                 if x:
93                     cls.ANGLE = angle
94                     break
95         elif conn_count == 3:
96             # 3 point connector, rotated correctly
97             cls.IMG = os.path.join('tunnel', 'tunnel_3way')
98             # find the missing connection.
99             for x, angle in zip(connections, (0, 180, 270, 90)):
100                 if not x:
101                     cls.ANGLE = angle
102                     break
103         elif conn_count == 2:
104             # Need to distinguish pass-through or corner, and
105             # rotate correctly
106             # neighbors is left, right then up, down
107             if connections[0] == connections[1]:
108                 cls.IMG = os.path.join('tunnel', 'tunnel_passthrough')
109                 if connections[0]:
110                     cls.ANGLE = 90
111             else:
112                 cls.IMG = os.path.join('tunnel', 'tunnel_corner')
113                 if connections[0]:
114                     if connections[2]:
115                         # left, up
116                         cls.ANGLE = 90
117                     else:
118                         # left, down
119                         cls.ANGLE = 180
120                 else:
121                     if connections[2]:
122                         # right, up
123                         cls.ANGLE = 0
124                     else:
125                         # right, down
126                         cls.ANGLE = 270
127
128         return super(Tunnel, cls).image(neighbors)
129