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