1 """Loader a level, using the pygame-zero ResourceLoader infrastructure"""
6 from pgzero.loaders import images, ResourceLoader
9 from pygame.transform import rotate
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))
21 class OrientatedTile(Tile):
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))
30 img = rotate(img, cls.ANGLE)
34 class RandomizedTile(Tile):
40 def image(cls, neighbors):
41 if cls.IMGDIR is None or cls.TILESET is None:
42 raise NotImplementedError()
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))
50 img = rotate(img, 90 * random.randint(0, 3))
54 class Floor(RandomizedTile):
57 class Wall(RandomizedTile):
60 class Underground(RandomizedTile):
61 IMGDIR = "underground"
63 class Tunnel(OrientatedTile):
66 def image(cls, neighbors):
67 connections = [True if 'walk' in x['behaviour'] else False for x in neighbors]
68 conn_count = connections.count(True)
72 # return single point tunnel
73 cls.IMG = os.path.join('tunnel', 'tunnel_none')
76 cls.IMG = os.path.join('tunnel', 'tunnel_crossroads')
78 # 1 point connector, roatated correctly
79 cls.IMG = os.path.join('tunnel', 'tunnel_1way')
80 # because of the ordering of neighbors, we use this formulation
81 for x, angle in zip(connections, (90, 270, 0, 180)):
86 # 3 point connector, rotated correctly
87 cls.IMG = os.path.join('tunnel', 'tunnel_3way')
88 # find the missing connection.
89 for x, angle in zip(connections, (0, 180, 270, 90)):
94 # Need to distinguish pass-through or corner, and
96 # neighbors is left, right then up, down
97 if connections[0] == connections[1]:
98 cls.IMG = os.path.join('tunnel', 'tunnel_passthrough')
102 cls.IMG = os.path.join('tunnel', 'tunnel_corner')
118 return super(Tunnel, cls).image(neighbors)
122 "cwall": Wall, # rename this everywhere
125 "underground": Underground,
128 class LevelLoader(ResourceLoader):
129 """ Level loader. """
134 def _load(self, level_path):
135 f = open(level_path, 'r')
136 level_data = json.load(f)
138 self._height = len(level_data['tiles'])
139 self._width = len(level_data['tiles'][0])
140 self._tiles = level_data['tiles']
141 self._tileset = level_data['tileset']
142 # Consistency check, so we can assume things are correct
143 # in the level renderer
144 for row, row_data in enumerate(self._tiles):
145 if len(row_data) != self._width:
146 raise RuntimeError("Incorrect len for row %d" % row)
147 for tile in TILES.values():
148 tile.TILESET = self._tileset
149 self._load_tile_images()
152 def _load_tile_images(self):
153 """Load all the tile images"""
154 height = len(self._tiles)
155 width = len(self._tiles[0])
156 for y, row_data in enumerate(self._tiles):
157 for x, tile in enumerate(row_data):
159 # 4 -connected neighbors
160 neighborhood = [self._tiles[y][x-1] if x > 0 else None,
161 self._tiles[y][x+1] if x < width - 1 else None,
162 self._tiles[y-1][x] if y > 0 else None,
163 self._tiles[y+1][x] if y < height- 1 else None,
165 for layer in ['floor', 'tunnels']:
166 neighbors = [x[layer] if x else None for x in neighborhood]
167 tile['%s image' % layer] = \
168 TILES[tile[layer]['base']].image(neighbors)
171 levels = LevelLoader('levels')