# HG changeset patch # User Jeremy Thurgood # Date 1378473267 -7200 # Node ID 282113d86d755001fdb94d8486517f7e5bf154b0 # Parent 4708e86a9a3cc7f439ca426311dee60417bfe893 Save door and lever state. diff -r 4708e86a9a3c -r 282113d86d75 data/levels/level1 --- a/data/levels/level1 Fri Sep 06 13:42:42 2013 +0200 +++ b/data/levels/level1 Fri Sep 06 15:14:27 2013 +0200 @@ -34,7 +34,7 @@ name: both_switches - args: - [620, 220] - - door_switch + - switch_door classname: FloorLight name: door_light - args: diff -r 4708e86a9a3c -r 282113d86d75 nagslang/game_object.py --- a/nagslang/game_object.py Fri Sep 06 13:42:42 2013 +0200 +++ b/nagslang/game_object.py Fri Sep 06 15:14:27 2013 +0200 @@ -127,6 +127,16 @@ self.interactible.set_game_object(self) self.remove = False # If true, will be removed from drawables + def set_stored_state_dict(self, stored_state): + """Override this to set up whatever state storage you want. + + The `stored_state` dict passed in contains whatever saved state we + might have for this object. If the return value of this method + evaluates to `True`, the contents of the `stored_state` dict will be + saved, otherwise it will be discarded. + """ + pass + def get_space(self): return self.physicser.get_space() @@ -270,21 +280,44 @@ self.shape.sensor = True self.destination = destination self.dest_pos = tuple(dest_pos) - puzzler = None - action = environment.Action(self._post_door_event) - if key_state is not None: - puzzler = puzzle.StateProxyPuzzler(key_state) - action.condition = environment.PuzzleStateCondition(puzzler) + self._key_state = key_state super(Door, self).__init__( SingleShapePhysicser(space, self.shape), - render.ImageRenderer(resources.get_image('objects', 'door.png')), - puzzler, - interactible=environment.Interactible(action), + render.ImageStateRenderer({ + True: resources.get_image('objects', 'door.png'), + # TODO: Locked door image. + False: resources.get_image('objects', 'door.png'), + }), + puzzle.ParentAttrPuzzler('is_open'), + interactible=environment.Interactible( + environment.Action( + self._post_door_event, + environment.FunctionCondition(lambda p: self.is_open))), ) + @property + def is_open(self): + return self._stored_state['is_open'] + def _post_door_event(self, protagonist): DoorEvent.post(self.destination, self.dest_pos) + def set_stored_state_dict(self, stored_state): + self._stored_state = stored_state + if self._key_state is not None: + # We're lockable, so we start locked and want to save our state. + self._stored_state.setdefault('is_open', False) + return True + # Not lockable, so we're always open and don't bother saving state. + self._stored_state['is_open'] = True + return False + + def update(self, dt): + if not self.is_open: + self._stored_state['is_open'] = self.puzzler.glue.get_state_of( + self._key_state) + super(Door, self).update(dt) + @classmethod def requires(cls): return [("name", "string"), ("position", "coordinates"), @@ -331,7 +364,6 @@ body = make_body(None, None, position) self.shape = pymunk.Circle(body, 20) self.shape.sensor = True - self.toggle_on = False super(ToggleSwitch, self).__init__( SingleShapePhysicser(space, self.shape), render.ImageStateRenderer({ @@ -344,8 +376,18 @@ environment.Action(self._toggle)), ) + @property + def toggle_on(self): + return self._stored_state['toggle_on'] + def _toggle(self, protagonist): - self.toggle_on = not self.toggle_on + self._stored_state['toggle_on'] = not self.toggle_on + + def set_stored_state_dict(self, stored_state): + self._stored_state = stored_state + # We start in the "off" position. + self._stored_state.setdefault('toggle_on', False) + return True @classmethod def requires(cls): diff -r 4708e86a9a3c -r 282113d86d75 nagslang/level.py --- a/nagslang/level.py Fri Sep 06 13:42:42 2013 +0200 +++ b/nagslang/level.py Fri Sep 06 15:14:27 2013 +0200 @@ -30,6 +30,7 @@ self.polygons = {} self.lines = [] self.world = world + self.world.level_state.setdefault(name, {}) self.basetile = 'tiles/floor.png' self._tile_image = None self._surface = None @@ -93,6 +94,14 @@ gobj = cls(*args) elif issubclass(cls, go.GameObject): gobj = cls(space, *args) + level_state = self.world.level_state[self.name] + stored_state = level_state.get(name, {}) + should_save = bool(gobj.set_stored_state_dict(stored_state)) + if should_save: + if name is None: + raise Exception( + "Unnamed game object wants to save state:" % (gobj,)) + level_state[name] = stored_state self.drawables.append(gobj) if gobj.overlay: self.overlay_drawables.append(gobj.overlay) diff -r 4708e86a9a3c -r 282113d86d75 nagslang/screens/menu.py --- a/nagslang/screens/menu.py Fri Sep 06 13:42:42 2013 +0200 +++ b/nagslang/screens/menu.py Fri Sep 06 15:14:27 2013 +0200 @@ -47,7 +47,7 @@ def play(self): level_name, pos = self.world.level - self.world.protagonist.set_position(pos) + self.world.protagonist.set_position(tuple(pos)) ScreenChange.post(level_name) def restart(self): diff -r 4708e86a9a3c -r 282113d86d75 nagslang/world.py --- a/nagslang/world.py Fri Sep 06 13:42:42 2013 +0200 +++ b/nagslang/world.py Fri Sep 06 15:14:27 2013 +0200 @@ -26,6 +26,7 @@ starting_position = (350, 300) self.protagonist = Protagonist(pymunk.Space(), self, starting_position) self.level = (first_level, starting_position) + self.level_state = {} def _save_location(self): app = 'nagslang' @@ -46,7 +47,7 @@ if hasattr(value, '__name__'): continue # Hack until we save protagonist state - if hasattr(value, 'update'): + if hasattr(value, 'update') and not isinstance(value, dict): continue data[attr] = value