Tweak logic around restarting, to avoid some bugs
authorNeil <neil@dip.sun.ac.za>
Sat, 20 Apr 2013 08:50:20 +0000 (10:50 +0200)
committerNeil <neil@dip.sun.ac.za>
Sat, 20 Apr 2013 08:50:20 +0000 (10:50 +0200)
erdslangetjie/__main__.py

index 885885ae7dfc4ba5e3eb78bbf03ae506b5ee17fe..8121eb92436228066feaae21e2d6de4962ac6582 100644 (file)
@@ -28,7 +28,6 @@ class GameWindow(RelativeLayout):
         self.level_obj = self.level_list.get_current_level()
         self.level_obj.load_tiles()
         self.tiles = {}
-        self.view = app.root
         self.app = app
 
         cols, rows = self.level_obj.get_size()
@@ -37,9 +36,6 @@ class GameWindow(RelativeLayout):
                 size=(cols * TILE_SIZE, rows * TILE_SIZE),
                 size_hint=(None, None))
 
-        self.x_scroll_margin = float(TILE_SIZE) / self.view.size[0]
-        self.y_scroll_margin = float(TILE_SIZE) / self.view.size[1]
-
         self.mouse_move = False
 
         self.caught = load_sound('sounds/caught.ogg')
@@ -54,15 +50,21 @@ class GameWindow(RelativeLayout):
         self.move_counter = 0
 
         self.player.pos = self.level_obj.enter_pos
-        if platform() != 'android':
+        self.keyboard = None
+        self._key_bound = False
+
+    def build(self):
+        if platform() != 'android' and not self.keyboard:
             # Very hack'ish
             # We need to delay this import until after the window creation by
             # the app, else our size config doesn't work
             from kivy.core.window import Window
             self.keyboard = Window.request_keyboard(self._closed, self)
+        if self.keyboard and not self._key_bound:
+            # We remove this binding when we're the not top level widget,
+            # so re-add it here
+            self._key_bound = True
             self.keyboard.bind(on_key_down=self._on_key_down)
-
-    def build(self):
         self.clear_widgets()
         self.tiles = {}
         tiles = self.level_obj.get_tiles()
@@ -86,6 +88,12 @@ class GameWindow(RelativeLayout):
                     texture=tile.texture)
         self.tiles[pos] = node
 
+    def fix_scroll_margins(self):
+        # We need to call this after app.root is set
+        self.view = self.app.root
+        self.x_scroll_margin = float(TILE_SIZE) / self.view.size[0]
+        self.y_scroll_margin = float(TILE_SIZE) / self.view.size[1]
+
     def draw_player(self):
         if self.player_tile:
             self.remove_widget(self.player_tile)
@@ -162,7 +170,8 @@ class GameWindow(RelativeLayout):
         self.add_widget(self.nemesis_tile)
 
     def _closed(self):
-        if platform() != 'android':
+        if self.keyboard:
+            self._key_bound = False
             self.keyboard.unbind(on_key_down=self._on_key_down)
 
     def _on_key_down(self, keyboard, keycode, text, modifiers):
@@ -215,6 +224,12 @@ class GameWindow(RelativeLayout):
     def check_caught(self):
         return self.nemesis.pos == self.player.pos
 
+    def stop_game(self):
+        Clock.unschedule(self.timed_move)
+        if self.nemesis_tile:
+            self.remove_widget(self.nemesis_tile)
+        self.nemesis.reset_pos()
+
     def reset_level(self):
         Clock.unschedule(self.timed_move)
         self.timer_set = False
@@ -227,7 +242,8 @@ class GameWindow(RelativeLayout):
         if self.level_obj:
             self.level_obj.load_tiles()
             self.player.pos = self.level_obj.enter_pos
-            self.remove_widget(self.player_tile)
+            if self.player_tile:
+                self.remove_widget(self.player_tile)
             self.view.scroll_x = 0
             self.view.scroll_y = 0
             self.build()
@@ -236,6 +252,9 @@ class GameWindow(RelativeLayout):
             return True
         return False
 
+    def do_reload(self):
+        self.level_obj = self.level_list.get_current_level()
+
     def check_state(self):
         if not self.level_obj:
             return
@@ -244,20 +263,16 @@ class GameWindow(RelativeLayout):
             # Jump to next level
             self.level_obj = self.level_list.advance_to_next_level()
             if not self.load_level():
-                app = self.app
-                self.app = None
                 self._closed()
-                app.game_over(True)
+                self.app.game_over(True)
             return
         elif self.check_caught():
             # Caught
             if self.app.config.getdefault('bane', 'sound', '0') != '0':
                 self.caught.play()
             self.reset_level()
-            app = self.app
-            self.app = None
             self._closed()
-            app.game_over(False)
+            self.app.game_over(False)
             return
         elif self.level_obj.is_button(self.player.pos):
             self.level_obj.trigger_button(self.player.pos)
@@ -382,6 +397,7 @@ class GameApp(App):
         level_name = self.config.getdefault('bane', 'start_level', None)
         if level_name:
             self.levels.set_level_to(level_name)
+        self.game = GameWindow(self.levels, self)
         return root
 
     def on_start(self):
@@ -408,10 +424,11 @@ class GameApp(App):
 
     def start_game(self, label, ref):
         """Start the game"""
-        self.game = GameWindow(self.levels, self)
-        self.game.build()
         self.root.clear_widgets()
         self.root.add_widget(self.game)
+        self.game.fix_scroll_margins()
+        self.game.reset_level()
+        self.game.load_level()
         # Ensure the player is visible
         self.root.scroll_x = 0
         self.root.scroll_y = 0
@@ -422,10 +439,10 @@ class GameApp(App):
         if won:
             screen = WonScreen(self)
             self.levels.reset()
+            self.game.do_reload()
         else:
             screen = LostScreen(self)
-        del self.game
-        self.game = None
+        self.game.stop_game()
         self.root.clear_widgets()
         self.root.add_widget(screen)