changeset 79:fe8652a060df

Simple menu screen and TextChoice widget
author Stefano Rivera <stefano@rivera.za.net>
date Mon, 04 Apr 2011 00:46:13 +0200
parents f29b7ada68c1
children 54141a2c46f9
files scripts/level-editor skaapsteker/__init__.py skaapsteker/__main__.py skaapsteker/engine.py skaapsteker/menuscene.py skaapsteker/widgets/__init__.py skaapsteker/widgets/text.py
diffstat 7 files changed, 112 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/level-editor	Mon Apr 04 00:42:33 2011 +0200
+++ b/scripts/level-editor	Mon Apr 04 00:46:13 2011 +0200
@@ -61,8 +61,9 @@
         tilepos = (position[0] // 64, position[1] // 64)
         text = Text("Level: %s.\nOffset: %r Tile: %r\nFPS: %.1f"
                     % (levelname, position, tilepos, sum(fpss)/len(fpss)),
+                    (10, 10),
                     color='white')
-        text.draw(screen_surface, (10, 10))
+        text.draw(screen_surface)
 
         pygame.display.flip()
         fpss = (fpss + [1000 / clock.tick(FRAMERATE)])[-FRAMERATE:]
--- a/skaapsteker/__init__.py	Mon Apr 04 00:42:33 2011 +0200
+++ b/skaapsteker/__init__.py	Mon Apr 04 00:46:13 2011 +0200
@@ -1,3 +0,0 @@
-if __name__ == "__main__":
-    import main
-    main.main()
--- a/skaapsteker/__main__.py	Mon Apr 04 00:42:33 2011 +0200
+++ b/skaapsteker/__main__.py	Mon Apr 04 00:46:13 2011 +0200
@@ -1,9 +1,10 @@
 """Game main module.
    """
 
-from constants import SCREEN, FREQ, BITSIZE, CHANNELS, BUFFER, DEBUG
-from engine import Engine
-from levelscene import LevelScene
+from .constants import SCREEN, FREQ, BITSIZE, CHANNELS, BUFFER, DEBUG
+from .engine import Engine
+from .levelscene import LevelScene
+from .menuscene import MenuScene
 
 import pygame
 from pygame.locals import SWSURFACE
@@ -48,15 +49,17 @@
     pygame.display.set_caption("Nine Tales")
 
     level = getattr(opts, 'level', None)
-    level = "level1" if level is None else level
 
     engine = Engine()
-    engine.change_scene(LevelScene(level))
+    if level is not None:
+        engine.change_scene(LevelScene(level))
+    else:
+        engine.change_scene(MenuScene())
     try:
         engine.run()
     except KeyboardInterrupt:
         pass
 
- 
+
 if __name__ == '__main__':
     main()
--- a/skaapsteker/engine.py	Mon Apr 04 00:42:33 2011 +0200
+++ b/skaapsteker/engine.py	Mon Apr 04 00:46:13 2011 +0200
@@ -39,7 +39,7 @@
 class Scene(object):
 
     def __init__(self):
-        pass
+        self.widgets = []
 
     def post(self, ev):
         """Post an event to pygame's event loop."""
@@ -55,11 +55,13 @@
 
     def dispatch(self, ev):
         """Dispatch an event."""
-        pass
+        for widget in self.widgets:
+            widget.dispatch(ev)
 
     def draw(self, surface):
         """Update the scene surface."""
-        pass
+        for widget in self.widgets:
+            widget.draw(surface)
 
 
 class UserEvent(object):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/skaapsteker/menuscene.py	Mon Apr 04 00:46:13 2011 +0200
@@ -0,0 +1,33 @@
+import pygame
+from pygame.locals import (K_ESCAPE, K_DOWN, K_UP, K_q, KEYDOWN, QUIT)
+
+from .engine import ChangeScene, Scene
+from .levelscene import LevelScene
+from .widgets.text import Text, TextChoice
+
+class MenuScene(Scene):
+    def __init__(self):
+        super(MenuScene, self).__init__()
+        self.widgets.append(Text("MENU:", (50, 50), color='white', size=48))
+        choice = TextChoice(("level1", "level2", "Quit"), (50, 100), color='white')
+        choice.callbacks.append(self.selected)
+        self.widgets.append(choice)
+
+    def selected(self, option):
+        "Callback from menu TextChoice"
+        if option == 0:
+            ChangeScene.post(LevelScene('level1'))
+        elif option == 1:
+            ChangeScene.post(LevelScene('level2'))
+        elif option == 2:
+            pygame.event.post(pygame.event.Event(QUIT))
+
+    def draw(self, surface):
+        surface.fill(pygame.Color('black'))
+        super(MenuScene, self).draw(surface)
+
+    def dispatch(self, ev):
+        if ev.type is KEYDOWN:
+            if ev.key in(K_q, K_ESCAPE):
+                pygame.event.post(pygame.event.Event(QUIT))
+        super(MenuScene, self).dispatch(ev)
--- a/skaapsteker/widgets/__init__.py	Mon Apr 04 00:42:33 2011 +0200
+++ b/skaapsteker/widgets/__init__.py	Mon Apr 04 00:46:13 2011 +0200
@@ -0,0 +1,9 @@
+class Widget(object):
+    def __init__(self):
+        pass
+
+    def dispatch(self, event):
+        pass
+
+    def draw(self, surface):
+        pass
--- a/skaapsteker/widgets/text.py	Mon Apr 04 00:42:33 2011 +0200
+++ b/skaapsteker/widgets/text.py	Mon Apr 04 00:46:13 2011 +0200
@@ -1,8 +1,12 @@
+# -*- coding: utf-8 -*-
+
 import os.path
 
 import pygame
+from pygame.locals import KEYDOWN, K_UP, K_DOWN, K_RETURN
 
-import skaapsteker.data
+from ..widgets import Widget
+from ..data import filepath
 
 fonts = {
     'sans': 'DejaVuSans.ttf',
@@ -10,26 +14,62 @@
 
 loaded_fonts = {}
 
-class Text(object):
-    def __init__(self, text, font='sans', size=16, color='black'):
+def load_font(name, size):
+    if (name, size) not in loaded_fonts:
+        fontfn = filepath('fonts/' + fonts[name])
+        fonts[(name, size)] = pygame.font.Font(fontfn, size)
+    return fonts[(name, size)]
+
+
+class Text(Widget):
+    def __init__(self, text, pos, font='sans', size=16, color='black'):
         self.text = text
+        if isinstance(pos, pygame.Rect):
+            self.rect = pos
+        else:
+            self.rect = pygame.Rect(pos, (0, 0))
         self.font = load_font(font, size)
         self.color = pygame.Color(color)
+        # TODO: Wrapping
         self.surfaces = [self.font.render(line, True, self.color)
                          for line in self.text.split('\n')]
+        self.rect.width = max(line.get_width() for line in self.surfaces)
+        self.rect.height = self.font.get_linesize() * len(self.surfaces)
 
-    def draw(self, surface, pos):
-        if isinstance(pos, pygame.Rect):
-            pos = pos.copy()
-        else:
-            pos = pygame.Rect(pos, (0, 0))
-
+    def draw(self, surface):
+        pos = self.rect.copy()
         for line in self.surfaces:
             surface.blit(line, pos)
             pos.move_ip(0, self.font.get_linesize())
 
-def load_font(name, size):
-    if (name, size) not in loaded_fonts:
-        fontfn = skaapsteker.data.filepath('fonts/' + fonts[name])
-        fonts[(name, size)] = pygame.font.Font(fontfn, size)
-    return fonts[(name, size)]
+
+class TextChoice(Widget):
+    def __init__(self, options, pos, **kwargs):
+        self.options = []
+        self.rect = pygame.Rect(pos, (0, 0))
+        self.selector = Text(u'ยป ', self.rect.copy(), **kwargs)
+        self.selected = 0
+        self.callbacks = []
+
+        pos = self.rect.move(self.selector.rect.width, 0)
+        for option in options:
+            t = Text(option, pos, **kwargs)
+            pos = pos.move(0, t.rect.height)
+            self.options.append(t)
+
+    def dispatch(self, ev):
+        if ev.type is KEYDOWN:
+            if ev.key == K_UP:
+                self.selected -= 1
+            elif ev.key == K_DOWN:
+                self.selected += 1
+            elif ev.key == K_RETURN:
+                all(callback(self.selected) for callback in self.callbacks)
+
+        self.selected %= len(self.options)
+        self.selector.rect.top = self.options[self.selected].rect.top
+
+    def draw(self, surface):
+        for option in self.options:
+            option.draw(surface)
+        self.selector.draw(surface)