Better menus, no default game.
authorJeremy Thurgood <firxen@gmail.com>
Fri, 16 May 2014 19:23:54 +0000 (21:23 +0200)
committerJeremy Thurgood <firxen@gmail.com>
Fri, 16 May 2014 19:23:54 +0000 (21:23 +0200)
naja/__main__.py
naja/scenes/menu.py
naja/widgets/base.py
naja/widgets/selector.py
naja/widgets/text.py

index bc60052528b1925aea465a91067cdb6ed9b478ad..44d1a065c4d94400e8a9fd989731a18206ad7c85 100644 (file)
@@ -8,7 +8,6 @@ from naja.engine import Engine
 from naja.sound import sound
 from naja.options import parse_args
 from naja.scenes.menu import MenuScene
-from naja.gamestate import GameState
 
 
 def main():
@@ -22,9 +21,8 @@ def main():
     sound.init()
 
     screen = pygame.display.get_surface()
-    state = GameState.new()
-    scene = MenuScene(state)
-    engine = Engine(screen, scene, state)
+    scene = MenuScene(None)
+    engine = Engine(screen, scene, None)
     engine.run()
 
 
index 560e104449a5808bdc064cb7d823ad4b52359476..327bb0b371f6222883d9370d68f4e469170fec4a 100644 (file)
@@ -4,7 +4,7 @@ Main menu scene.
 
 import pygame.locals as pgl
 
-from naja.constants import KEYS
+from naja.constants import KEYS, PALETTE
 from naja.events import SceneChangeEvent, QuitGameEvent
 from naja.scenes.scene import Scene
 from naja.scenes.credits import CreditsScene
@@ -20,37 +20,47 @@ class MenuScene(Scene):
         super(MenuScene, self).__init__(state)
         selector = SelectorWidget()
         self.add(selector)
+        y_offset = 0
 
-        run_game = TextWidget((100, 50), 'Game', fontsize=32, colour='white')
-        run_game.add_callback(
-            'click', lambda event: SceneChangeEvent.post(GameScene))
-        selector.add(run_game)
+        y_offset += 50
+        resume = TextWidget(
+            (100, y_offset), 'Resume Game', colour=PALETTE.WHITE,
+            unselectable_colour=PALETTE.GREY)
+        resume.add_callback('click', self.scene_callback(GameScene))
+        resume.set_selectable_callback(lambda: state is not None)
+        selector.add(resume)
 
-        new_game = TextWidget((100, 100), 'New', fontsize=32, colour='white')
-        new_game.add_callback(
-            'click', lambda event: SceneChangeEvent.post(NewGameScene))
-        selector.add(new_game)
+        y_offset += 50
+        new = TextWidget((100, y_offset), 'New Game', colour=PALETTE.WHITE)
+        new.add_callback('click', self.scene_callback(NewGameScene))
+        selector.add(new)
 
-        credits = TextWidget(
-            (100, 150), 'Credits', fontsize=32, colour='white')
-        credits.add_callback(
-            'click', lambda event: SceneChangeEvent.post(CreditsScene))
-        selector.add(credits)
-
-        load = TextWidget((100, 200), 'Load', fontsize=32, colour='white')
-        load.add_callback(
-            'click', lambda event: SceneChangeEvent.post(LoadGameScene))
+        y_offset += 50
+        load = TextWidget((100, y_offset), 'Load', colour=PALETTE.WHITE)
+        load.add_callback('click', self.scene_callback(LoadGameScene))
         selector.add(load)
 
-        save = TextWidget((100, 250), 'Save', fontsize=32, colour='white')
-        save.add_callback(
-            'click', lambda event: SceneChangeEvent.post(SaveGameScene))
+        y_offset += 50
+        save = TextWidget(
+            (100, y_offset), 'Save', colour=PALETTE.WHITE,
+            unselectable_colour=PALETTE.GREY)
+        save.add_callback('click', self.scene_callback(SaveGameScene))
+        save.set_selectable_callback(lambda: state is not None)
         selector.add(save)
 
-        quit = TextWidget((100, 300), 'Quit', fontsize=32, colour='white')
+        y_offset += 50
+        credits = TextWidget((100, y_offset), 'Credits', colour=PALETTE.WHITE)
+        credits.add_callback('click', self.scene_callback(CreditsScene))
+        selector.add(credits)
+
+        y_offset += 50
+        quit = TextWidget((100, y_offset), 'Quit', colour=PALETTE.WHITE)
         quit.add_callback('click', lambda event: QuitGameEvent.post())
         selector.add(quit)
 
+    def scene_callback(self, scene_class):
+        return lambda event: SceneChangeEvent.post(scene_class)
+
     def handle_scene_event(self, ev):
         if ev.type == pgl.KEYDOWN:
             if ev.key in KEYS.QUIT:
index ee6190b91939bdd35176e11257fc570ac2a78adf..815d1d3a3f1cf23fedcc776ff980b5d4b727b051 100644 (file)
@@ -7,6 +7,8 @@ from naja.events import InvalidateTheWorld, SelectEvent
 
 
 class Widget(object):
+    _is_selectable_func = None
+
     def __init__(self, pos, size=None):
         self.pos = pos
         self.size = size or (0, 0)
@@ -50,6 +52,16 @@ class Widget(object):
             callback(event)
         return bool(self.callbacks[event])
 
+    def set_selectable_callback(self, func):
+        self._is_selectable_func = func
+
+    def is_selectable(self):
+        """Return False if this widget isn't selectable by SelectorWidget."""
+        if self._is_selectable_func is not None:
+            return self._is_selectable_func()
+        else:
+            return True
+
 
 class Container(object):
     def __init__(self, *widgets):
index 4479b72adf5236e532b1b0535127408341621a94..dcbc74498b930b3e4d2b31aa6318eae7d59d6b57 100644 (file)
@@ -18,18 +18,26 @@ class SelectorWidget(Container):
         super(SelectorWidget, self).render(surface)
         pos = self.selector.get_rect()
         selected = self.widgets[self.position]
+        if not selected.is_selectable():
+            selected = self.change_pos(1)
+
         pos = pos.move(selected.pos)
         pos = pos.move(-pos.width * 1.5, (selected.size[1] - pos.height) / 2)
         surface.blit(self.selector, pos)
 
+    def change_pos(self, change):
+        self.position = (self.position + change) % len(self.widgets)
+        while not self.widgets[self.position].is_selectable():
+            self.position = (self.position + change) % len(self.widgets)
+        return self.widgets[self.position]
+
     def handle_event(self, ev):
         if ev.type == pgl.KEYDOWN:
             if ev.key in KEYS.UP + KEYS.DOWN:
                 if ev.key in KEYS.DOWN:
-                    self.position += 1
+                    self.change_pos(1)
                 else:
-                    self.position -= 1
-                self.position %= len(self.widgets)
+                    self.change_pos(-1)
                 sound.play_sound('zoop.ogg', volume=0.05)
                 return True
             elif ev.key in KEYS.SELECT:
index 4343d015e2519f77b48accf314f1d99bf21fe65d..9eba104065a18a2a84a4a947f683811f8c2e9241 100644 (file)
@@ -37,16 +37,22 @@ class Glyph(object):
 class TextWidget(Widget):
 
     def __init__(self, pos, text, size=None, fontname=None, fontsize=None,
-                 colour=None):
+                 colour=None, unselectable_colour=None):
         super(TextWidget, self).__init__(pos, size)
 
         self.text = text
         self.fontname = fontname or FONT
         self.fontsize = (fontsize or FONT_SIZE) // EIGHT_BIT_SCALE
         self.colour = convert_colour(colour or PALETTE.BLACK)
+        if unselectable_colour is not None:
+            unselectable_colour = convert_colour(unselectable_colour)
+        self.unselectable_colour = unselectable_colour
 
     def render_line(self, text):
-        text_surf = self.font.render(text, True, self.colour)
+        colour = self.colour
+        if not self.is_selectable() and self.unselectable_colour is not None:
+            colour = self.unselectable_colour
+        text_surf = self.font.render(text, True, colour)
         text_rect = text_surf.get_rect()
         return pygame.transform.scale(
             text_surf, (text_rect.width * EIGHT_BIT_SCALE,