Move viewport management down into the engine and add suitable events. Cache initial...
[koperkapel.git] / koperkapel / scenes / level.py
1 """Render a level"""
2
3 from pgzero.constants import keys
4 from pygame import Surface
5 from ..loaders.levelloader import levels
6 from .base import Scene, ChangeSceneEvent
7 from ..constants import TILE_SIZE, WIDTH, HEIGHT
8
9
10 class LevelScene(Scene):
11     """ Level scene. """
12
13     def __init__(self, level_name):
14         self._level_data = levels.load(level_name)
15         self._tiles = self._level_data['tiles']
16         self._surface = None
17         self._render()
18
19     def _render(self):
20         # We cache the rendered surface to avoid doing a large number
21         # of blits each frame, as that introduces a large performance
22         # overhead.
23         self._surface = Surface((len(self._tiles[0]) * TILE_SIZE,
24                                  len(self._tiles) * TILE_SIZE))
25         for y, row in enumerate(self._tiles):
26             for x, tile in enumerate(row):
27                 pos = (x * TILE_SIZE, y * TILE_SIZE)
28                 if 'image' not in tile:
29                     # Skip broken tiles for now
30                     continue
31                 self._surface.blit(tile['image'], pos)
32
33     def draw(self, screen, viewport):
34         screen.clear()
35         # Viewport is the position of the screen relative to the
36         # surface. We need the position of the surface relative to
37         # the screen for the blit, so this conversion
38         screen_pos = -viewport[0], -viewport[1]
39         screen.blit(self._surface, screen_pos)
40
41     def on_key_down(self, key, mod, unicode):
42         if key == keys.ESCAPE:
43             from .menu import MenuScene
44             return [ChangeSceneEvent(MenuScene())]