X-Git-Url: https://git.ctpug.org.za/?a=blobdiff_plain;f=koperkapel%2Fscenes%2Fbase.py;h=24a8c615fa06c43f97fe893f302d5aab3197f26b;hb=31ec0ae3dc918618849b41c4df6b064d6a47c69f;hp=9bad13cd9f03b9e1d172c9c977ae575002a51c88;hpb=d7890e6e4eb3a93e3ccb24314e5b98760b0f99b9;p=koperkapel.git diff --git a/koperkapel/scenes/base.py b/koperkapel/scenes/base.py index 9bad13c..24a8c61 100644 --- a/koperkapel/scenes/base.py +++ b/koperkapel/scenes/base.py @@ -13,11 +13,14 @@ def apply_events(f): class Engine: - """ A holder for game state. """ + """ A holder for game state & scene management. + """ - def __init__(self, app, scene): + def __init__(self, app, scene, world): self._app = app self._scene = scene + self._world = world + self._update_vehicle = False def _apply_events(self, events): if not events: @@ -26,13 +29,25 @@ class Engine: ev.apply(self) def change_scene(self, scene): - self._scene.exit() + print('here', self._scene) + self._apply_events(self._scene.exit(self._world.proxy())) self._scene = scene - self._scene.enter() + print('there', self._scene) + self._apply_events(self._scene.enter(self._world.proxy())) + + def change_world(self, *args, **kw): + self._world.apply_event(*args, **kw) + + def quit_game(self): + from pgzero.game import exit + exit() + + def move_screen(self, offset): + self._scene.move_screen(offset) @apply_events def update(self, dt): - return self._scene.update(dt) + return self._scene.update(self._world.proxy(), self, dt) def draw(self): self._scene.draw(self._app.screen) @@ -77,20 +92,125 @@ class ChangeSceneEvent(Event): ENGINE_METHOD = "change_scene" +class WorldEvent(Event): + """ Be a hero. Change the world. """ + + ENGINE_METHOD = "change_world" + + +class QuitEvent(Event): + """ Quit the game. """ + + ENGINE_METHOD = "quit_game" + + +class MoveViewportEvent(Event): + """ Change to a new scene. """ + + ENGINE_METHOD = "move_screen" + + +class Layer: + """ A single layer of actors. """ + + def __init__(self, name): + self.name = name + self.actors = [] + + def __iter__(self): + return iter(self.actors) + + def __getitem__(self, i): + return self.actors[i] + + def __len__(self): + return len(self.actors) + + def add(self, actor): + self.actors.append(actor) + return actor + + def clear(self): + self.actors.clear() + + def remove(self, actor): + self.actors.remove(actor) + return actor + + +class Actors: + """ Layers of actors. + + Actors may be rendered in different layers. Layers with lower levels + are rendered lower than layers with higher ones. + """ + + def __init__(self): + self._ordered_layers = [] + self._layers = {} + self.add_layer("default", 0) + + def __getattr__(self, name): + return self._layers[name] + + def add_layer(self, name, level): + layer = self._layers[name] = Layer(name) + self._ordered_layers.append((level, name)) + self._ordered_layers.sort() + return layer + + def add(self, actor, layer="default"): + return self._layers[layer].add(actor) + + def remove(self, actor, layer="default"): + return self._layers[layer].remove(actor) + + def draw(self, screen): + for lvl, name in self._ordered_layers: + for actor in self._layers[name]: + # actor.draw doesn't allow blitting to anything other than + # the game scene + screen.blit(actor._surf, actor.topleft) + + +def defer_to_update(f): + """ Defers a function until the next update run. """ + @functools.wraps(f) + def wrapper(self, *args, **kw): + self._deferred_updates.append((f, args, kw)) + return wrapper + + class Scene: """ Base class for scenes. """ - def enter(self): - pass + def __init__(self): + self.actors = Actors() + self.viewport = (0, 0) + self._deferred_updates = [] - def exit(self): + def move_screen(self, offset): + self.viewport = (self.viewport[0] + offset[0], + self.viewport[1] + offset[1]) + + def calc_offset(self, x, y): + """ Return a position offset by the viewport. """ + return x - self.viewport[0], y - self.viewport[1] + + def enter(self, world): pass - def update(self, dt): + def exit(self, world): pass + def update(self, world, engine, dt): + deferred_updates, self._deferred_updates = self._deferred_updates, [] + for f, args, kw in deferred_updates: + f(self, world, *args, **kw) + def draw(self, screen): - pass + screen.clear() + self.actors.draw(screen) def on_mouse_down(self, pos, button): pass