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))
27 def image(cls, neighbors):
28 if cls.IMG is None or cls.TILESET is None:
29 raise NotImplementedError()
30 img = images.load(os.path.join(cls.TILESET, cls.IMG))
32 img = rotate(img, cls.ANGLE)
36 class RandomizedTile(Tile):
42 def image(cls, neighbors):
43 if cls.IMGDIR is None or cls.TILESET is None:
44 raise NotImplementedError()
46 imgdir = os.path.join(os.path.dirname(__file__), '..', 'images',
47 cls.TILESET, cls.IMGDIR)
48 imgpath = os.path.splitext(random.choice(os.listdir(imgdir)))[0]
49 img = images.load(os.path.join(cls.TILESET, cls.IMGDIR, imgpath))
52 img = rotate(img, 90 * random.randint(0, 3))
56 class Floor(RandomizedTile):
59 class Wall(RandomizedTile):
62 class Underground(RandomizedTile):
63 IMGDIR = "underground"
65 class Tunnel(OrientatedTile):
68 def image(cls, neighbors):
69 connections = [True if 'walk' in x['behaviour'] else False for x in neighbors]
70 conn_count = connections.count(True)
74 # return single point tunnel
75 cls.IMG = os.path.join('tunnel', 'tunnel_none')
78 cls.IMG = os.path.join('tunnel', 'tunnel_crossroads')
80 # 1 point connector, roatated correctly
81 cls.IMG = os.path.join('tunnel', 'tunnel_1way')
82 # because of the ordering of neighbors, we use this formulation
83 for x, angle in zip(connections, (90, 270, 0, 180)):
88 # 3 point connector, rotated correctly
89 cls.IMG = os.path.join('tunnel', 'tunnel_3way')
90 # find the missing connection.
91 for x, angle in zip(connections, (0, 180, 270, 90)):
96 # Need to distinguish pass-through or corner, and
98 # neighbors is left, right then up, down
99 if connections[0] == connections[1]:
100 cls.IMG = os.path.join('tunnel', 'tunnel_passthrough')
104 cls.IMG = os.path.join('tunnel', 'tunnel_corner')
120 return super(Tunnel, cls).image(neighbors)
124 "cwall": Wall, # rename this everywhere
127 "underground": Underground,
130 class LevelLoader(ResourceLoader):
131 """ Level loader. """
136 def _load(self, level_path):
137 f = open(level_path, 'r')
138 level_data = json.load(f)
140 self._height = len(level_data['tiles'])
141 self._width = len(level_data['tiles'][0])
142 self._tiles = level_data['tiles']
143 self._tileset = level_data['tileset']
144 # Consistency check, so we can assume things are correct
145 # in the level renderer
146 for row, row_data in enumerate(self._tiles):
147 if len(row_data) != self._width:
148 raise RuntimeError("Incorrect len for row %d" % row)
149 for tile in TILES.values():
150 tile.TILESET = self._tileset
151 self._load_tile_images()
154 def _load_tile_images(self):
155 """Load all the tile images"""
156 height = len(self._tiles)
157 width = len(self._tiles[0])
158 for y, row_data in enumerate(self._tiles):
159 for x, tile in enumerate(row_data):
161 # 4 -connected neighbors
162 neighborhood = [self._tiles[y][x-1] if x > 0 else None,
163 self._tiles[y][x+1] if x < width - 1 else None,
164 self._tiles[y-1][x] if y > 0 else None,
165 self._tiles[y+1][x] if y < height- 1 else None,
167 for layer in ['floor', 'tunnels']:
168 neighbors = [x[layer] if x else None for x in neighborhood]
169 tile['%s image' % layer] = \
170 TILES[tile[layer]['base']].image(neighbors)
173 levels = LevelLoader('levels')