# HG changeset patch # User Stefano Rivera # Date 1301870773 -7200 # Node ID fe8652a060df0839d7f122ff3535520832c45b2e # Parent f29b7ada68c1373370bfe42365f774c12973379d Simple menu screen and TextChoice widget diff -r f29b7ada68c1 -r fe8652a060df scripts/level-editor --- 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:] diff -r f29b7ada68c1 -r fe8652a060df skaapsteker/__init__.py --- 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() diff -r f29b7ada68c1 -r fe8652a060df skaapsteker/__main__.py --- 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() diff -r f29b7ada68c1 -r fe8652a060df skaapsteker/engine.py --- 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): diff -r f29b7ada68c1 -r fe8652a060df skaapsteker/menuscene.py --- /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) diff -r f29b7ada68c1 -r fe8652a060df skaapsteker/widgets/__init__.py --- 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 diff -r f29b7ada68c1 -r fe8652a060df skaapsteker/widgets/text.py --- 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)