ff18fc7b8e0548678dc172dd65db893fe33853fc
[koperkapel.git] / koperkapel / loaders / levelloader.py
1 """Loader a level, using the pygame-zero ResourceLoader infrastructure"""
2
3 import json
4
5 from pgzero.loaders import images, ResourceLoader
6 import os
7 import random
8 from pygame.transform import rotate
9
10 class Tile:
11     IMG = None
12
13     @classmethod
14     def image(cls):
15         if cls.IMG is None:
16             raise NotImplementedError()
17
18         return images.load(cls.IMG)
19
20 class RandomizedTile(Tile):
21     IMGDIR = None
22     ROTATE = True
23
24     @classmethod
25     def image(cls):
26         if cls.IMGDIR is None:
27             raise NotImplementedError()
28
29         imgdir = os.path.join(os.path.dirname(__file__), '..', 'images', cls.IMGDIR)
30         imgpath = os.path.splitext(random.choice(os.listdir(imgdir)))[0]
31         img = images.load(os.path.join(cls.IMGDIR, imgpath))
32
33         if cls.ROTATE:
34             img = rotate(img, 90 * random.randint(0, 3))
35
36         return img
37
38 class Floor(RandomizedTile):
39     IMGDIR = "floor"
40
41 class Wall(RandomizedTile):
42     IMGDIR = "wall"
43
44 TILES = {
45     "cwall": Wall, # rename this everywhere
46     "floor": Floor,
47 }
48
49 class LevelLoader(ResourceLoader):
50     """ Level loader. """
51
52     EXTNS = ['json']
53     TYPE = 'level'
54
55     def _load(self, level_path):
56         f = open(level_path, 'r')
57         level_data = json.load(f)
58         f.close()
59         self._height = len(level_data['tiles'])
60         self._width = len(level_data['tiles'][0])
61         self._tiles = level_data['tiles']
62         # Consistency check, so we can assume things are correct
63         # in the level renderer
64         for row, row_data in enumerate(self._tiles):
65             if len(row_data) != self._width:
66                 raise RuntimeError("Incorrect len for row %d" % row)
67         self._load_tile_images()
68         return level_data
69
70     def _load_tile_images(self):
71         """Load all the tile images"""
72         for row_data in self._tiles:
73             for tile in row_data:
74                 tile['image'] = TILES[tile['base']].image()
75
76
77 levels = LevelLoader('levels')