544777c6aea5dfb60d001857b9769a4bf9920cb8
[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     TILESET = None
14
15     @classmethod
16     def image(cls):
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 RandomizedTile(Tile):
22     IMGDIR = None
23     TILESET = None
24     ROTATE = None
25
26     @classmethod
27     def image(cls):
28         if cls.IMGDIR is None or cls.TILESET is None:
29             raise NotImplementedError()
30
31         imgdir = os.path.join(os.path.dirname(__file__), '..', 'images',
32                 cls.TILESET, cls.IMGDIR)
33         imgpath = os.path.splitext(random.choice(os.listdir(imgdir)))[0]
34         img = images.load(os.path.join(cls.TILESET, cls.IMGDIR, imgpath))
35
36         if cls.ROTATE:
37             img = rotate(img, 90 * random.randint(0, 3))
38
39         return img
40
41 class Floor(RandomizedTile):
42     IMGDIR = "floor"
43
44 class Wall(RandomizedTile):
45     IMGDIR = "wall"
46
47 TILES = {
48     "cwall": Wall, # rename this everywhere
49     "floor": Floor,
50 }
51
52 class LevelLoader(ResourceLoader):
53     """ Level loader. """
54
55     EXTNS = ['json']
56     TYPE = 'level'
57
58     def _load(self, level_path):
59         f = open(level_path, 'r')
60         level_data = json.load(f)
61         f.close()
62         self._height = len(level_data['tiles'])
63         self._width = len(level_data['tiles'][0])
64         self._tiles = level_data['tiles']
65         self._tileset = level_data['tileset']
66         # Consistency check, so we can assume things are correct
67         # in the level renderer
68         for row, row_data in enumerate(self._tiles):
69             if len(row_data) != self._width:
70                 raise RuntimeError("Incorrect len for row %d" % row)
71         for tile in TILES.values():
72             tile.TILESET = self._tileset
73         self._load_tile_images()
74         return level_data
75
76     def _load_tile_images(self):
77         """Load all the tile images"""
78         for row_data in self._tiles:
79             for tile in row_data:
80                 for layer in ['floor', 'tunnels']:
81                     tile['%s image' % layer] = TILES[tile[layer]['base']].image()
82
83
84 levels = LevelLoader('levels')