changeset 120:48d24a48d0ce

Enter and leave hooks
author Neil Muller <neil@dip.sun.ac.za>
date Tue, 24 Aug 2010 17:24:54 +0200
parents d5f7cccfdb6c
children 2f672e98d488
files gamelib/constants.py gamelib/gamescreen.py gamelib/scenes/bridge.py gamelib/scenes/cryo.py gamelib/state.py
diffstat 5 files changed, 79 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/gamelib/constants.py	Tue Aug 24 17:04:56 2010 +0200
+++ b/gamelib/constants.py	Tue Aug 24 17:24:54 2010 +0200
@@ -14,3 +14,5 @@
 FRAME_RATE = 25
 
 DEBUG = True
+
+ENTER, LEAVE = 1, 2
--- a/gamelib/gamescreen.py	Tue Aug 24 17:04:56 2010 +0200
+++ b/gamelib/gamescreen.py	Tue Aug 24 17:24:54 2010 +0200
@@ -75,25 +75,33 @@
     def draw(self, surface):
         self.state.draw(surface)
 
+    def _process_result(self, result):
+        """Helper function to do the right thing with a result object"""
+        if result:
+            if result.sound:
+                result.sound.play()
+            if result.message:
+                # Display the message as a modal dialog
+                MessageDialog(result.message, 60).present()
+                # queue a redraw to show updated state
+                self.invalidate()
+
     def mouse_down(self, event):
         if self.subwidgets:
             self.remove(self.detail)
             self.state.set_current_detail(None)
         else:
             result = self.state.interact(event.pos)
-            if result:
-                if result.sound:
-                    result.sound.play()
-                if result.message:
-                    # Display the message as a modal dialog
-                    MessageDialog(result.message, 60).present()
-                    # queue a redraw to show updated state
-                    self.invalidate()
+            self._process_result(result)
 
     def animate(self):
         if self.state.animate():
             # queue a redraw
             self.invalidate()
+        # We do this here so we can get enter and leave events regardless
+        # of what happens
+        result = self.state.check_enter_leave()
+        self._process_result(result)
 
     def mouse_move(self, event):
         if not self.subwidgets:
--- a/gamelib/scenes/bridge.py	Tue Aug 24 17:04:56 2010 +0200
+++ b/gamelib/scenes/bridge.py	Tue Aug 24 17:24:54 2010 +0200
@@ -1,6 +1,6 @@
 """Bridge where the final showdown with the AI occurs."""
 
-from gamelib.state import Scene, Item, Thing
+from gamelib.state import Scene, Item, Thing, Result
 
 
 class Bridge(Scene):
@@ -17,5 +17,9 @@
         'accessible': False,
         }
 
+    def enter(self):
+        return Result("The bridge is in a sorry, shabby state")
+
+
 
 SCENES = [Bridge]
--- a/gamelib/scenes/cryo.py	Tue Aug 24 17:04:56 2010 +0200
+++ b/gamelib/scenes/cryo.py	Tue Aug 24 17:24:54 2010 +0200
@@ -15,6 +15,7 @@
 
     INITIAL_DATA = {
         'accessible': True,
+        'greet' : True
         }
 
     def __init__(self, state):
@@ -25,6 +26,15 @@
         self.add_thing(CryoRoomDoor())
         self.add_thing(CryoComputer())
 
+    def enter(self):
+        if self.get_data('greet'):
+            self.set_data('greet', False)
+            return Result("Greetings Prisoner id. You have woken early under"
+                    " the terms of the emergency conscription act to help with"
+                    " repairs to the ship. Your behaviour during this time will"
+                    " be added to your record and will be relayed to "
+                    " prison officials when we reach the destination."
+                    " Please report to the bridge.")
 
 class Triangle(Item):
     "Test item. Needs to go away at some point."
--- a/gamelib/state.py	Tue Aug 24 17:04:56 2010 +0200
+++ b/gamelib/state.py	Tue Aug 24 17:24:54 2010 +0200
@@ -30,6 +30,7 @@
     #state.load_scenes("machine")
     #state.load_scenes("map")
     state.set_current_scene("cryo")
+    state.set_do_enter_leave()
     return state
 
 
@@ -57,6 +58,11 @@
         self.current_scene = None
         # current detail view
         self.current_detail = None
+        # scene we came from, for enter and leave processing
+        self.previous_scene = None
+        # scene transion helpers
+        self.do_check = None
+        self.old_pos = None
 
     def add_scene(self, scene):
         self.scenes[scene.name] = scene
@@ -76,7 +82,11 @@
                 self.add_detail_view(scene_cls(self))
 
     def set_current_scene(self, name):
+        old_scene = self.current_scene
         self.current_scene = self.scenes[name]
+        if old_scene and old_scene != self.current_scene:
+            self.previous_scene = old_scene
+            self.set_do_enter_leave()
 
     def set_current_detail(self, name):
         if name is None:
@@ -98,7 +108,11 @@
         self.tool = item
 
     def draw(self, surface):
-        self.current_scene.draw(surface)
+        if self.do_check and self.previous_scene and self.do_check == constants.LEAVE:
+            # We still need to handle leave events, so still display the scene
+            self.previous_scene.draw(surface)
+        else:
+            self.current_scene.draw(surface)
 
     def draw_detail(self, surface):
         self.current_detail.draw(surface)
@@ -110,10 +124,33 @@
         return self.current_detail.interact(self.tool, pos)
 
     def animate(self):
-        return self.current_scene.animate()
+        if not self.do_check:
+            return self.current_scene.animate()
+
+    def check_enter_leave(self):
+        if not self.do_check:
+            return None
+        if self.do_check == constants.LEAVE:
+            self.do_check = constants.ENTER
+            if self.previous_scene:
+                return self.previous_scene.leave()
+            return None
+        elif self.do_check == constants.ENTER:
+            self.do_check = None
+            # Fix descriptions, etc.
+            if self.old_pos:
+                self.current_scene.mouse_move(self.tool, self.old_pos)
+            return self.current_scene.enter()
+        raise RuntimeError('invalid do_check value %s' % self.do_check)
 
     def mouse_move(self, pos):
         self.current_scene.mouse_move(self.tool, pos)
+        # So we can do sensible things on enter and leave
+        self.old_pos = pos
+
+    def set_do_enter_leave(self):
+        """Flag that we need to run the enter loop"""
+        self.do_check = constants.LEAVE
 
     def mouse_move_detail(self, pos):
         self.current_detail.mouse_move(self.tool, pos)
@@ -226,6 +263,13 @@
                 result = True
         return result
 
+    def enter(self):
+        return None
+
+    def leave(self):
+        self._current_description = None
+        return None
+
     def mouse_move(self, item, pos):
         """Call to check whether the cursor has entered / exited a thing.