# HG changeset patch # User Rizmari Versfeld # Date 1336343279 -7200 # Node ID 0e178b20e3ff347ded210eefc95ba623bfea55b2 # Parent d82d3e54a4efa6a3225054d1c09a3d6dc87bdc5a# Parent efc4f90cfd63faa451fcb289bcbf2465a1d36d36 merge commit diff -r efc4f90cfd63 -r 0e178b20e3ff data/images/button_down.png Binary file data/images/button_down.png has changed diff -r efc4f90cfd63 -r 0e178b20e3ff data/images/button_normal.png Binary file data/images/button_normal.png has changed diff -r efc4f90cfd63 -r 0e178b20e3ff gamelib/gui.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gamelib/gui.py Mon May 07 00:27:59 2012 +0200 @@ -0,0 +1,28 @@ +from pygame import image + +from gamelib import data +from gamelib.gui_base import Drawable, TextButton + + +class ImageDrawable(Drawable): + + def __init__(self, rect, image): + super(ImageDrawable, self).__init__(rect) + self.image = image + + def draw(self, surface): + surface.blit(self.image, (self.rect[0], self.rect[1])) + + +class BigButton(TextButton): + WIDTH = 128 + HEIGHT = 64 + BG_IMAGE_NORMAL = image.load(data.filepath('images/button_normal.png')) + BG_IMAGE_DOWN = image.load(data.filepath('images/button_down.png')) + + def __init__(self, pos, text): + rect1 = (0, 0, self.WIDTH, self.HEIGHT) + n = ImageDrawable(rect1, self.BG_IMAGE_NORMAL) + d = ImageDrawable(rect1, self.BG_IMAGE_DOWN) + rect2 = (pos[0], pos[1], self.WIDTH, self.HEIGHT) + super(BigButton, self).__init__(rect2, n, d, text) diff -r efc4f90cfd63 -r 0e178b20e3ff gamelib/gui_base.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gamelib/gui_base.py Mon May 07 00:27:59 2012 +0200 @@ -0,0 +1,171 @@ +import pygame +from pygame import Surface, Rect +from pygame.font import Font + +from gamelib import data + + +# different font sizes +pygame.font.init() +font_small = Font(data.filepath('fonts/DejaVuSans.ttf'), 10) +font_medium = Font(data.filepath('fonts/DejaVuSans.ttf'), 14) +font_large = Font(data.filepath('fonts/DejaVuSans.ttf'), 18) + + +class Drawable(object): + + def __init__(self, rect): + if isinstance(rect, Rect): + self.rect = rect + else: + self.rect = Rect(rect[0], rect[1], rect[2], rect[3]) + + def draw(self, surface): + pass + + +class Clickable(object): + + def on_mouse_down(self, pos): + pass + + def on_mouse_up(self, pos): + pass + + def on_mouse_move(self, pos): + pass + + def on_mouse_cancel(self): + pass + + def on_click(self): + pass + + +class ContainerView(Drawable): + + def __init__(self): + self.children = [] + + def add_child(self, child): + self.children.append(child) + + def remove_child(self, child): + self.children.remove(child) + + def get_child_by_pos(self, pos): + for child in self.children: + if child.rect.collidepoint(pos): + if isinstance(child, ContainerView): + # calculates position relative to child + x = pos[0] - child.rect[0] + y = pos[1] - child.rect[1] + return child.get_child_by_pos((x, y)) + else: + return child + + def draw_children(self, surface): + for child in self.children: + child.draw(surface) + + +class Window(Clickable, ContainerView): + + def __init__(self, screen): + super(Window, self).__init__() + self.surface = Surface((screen.get_width(), screen.get_height())) + self.background_colour = None + self.background_image = None + self.pressed_child = None + + def on_mouse_down(self, pos): + child = self.get_child_by_pos(pos) + if isinstance(child, Clickable): + # calculates position relative to child + x = pos[0] - child.rect[0] + y = pos[1] - child.rect[1] + child.on_mouse_down((x, y)) + self.pressed_child = child + + def on_mouse_up(self, pos): + if self.pressed_child: + child = self.pressed_child + x = pos[0] - child.rect[0] + y = pos[1] - child.rect[1] + child.on_mouse_up((x, y)) + self.pressed_child = None + + def on_mouse_move(self, pos): + if self.pressed_child: + if self.pressed_child != self.get_child_by_pos(pos): + self.pressed_child.on_mouse_cancel() + self.pressed_child = None + + def draw(self, screen): + if self.background_colour: + self.surface.fill(self.background_colour) + if self.background_image: + self.surface.blit(self.background_image, (0, 0)) + self.draw_children(self.surface) + screen.blit(self.surface, (0, 0)) + + +class StateDrawable(Drawable): + + def __init__(self, rect): + super(StateDrawable, self).__init__(rect) + self.state = -1 + self.states = {} + self.drawables = [] + self.surface = Surface((self.rect[2], self.rect[3])) + + def draw(self, surface): + if self.state != -1 and self.drawables[self.state]: + self.drawables[self.state].draw(surface) + + def add_state(self, state_name, drawable): + self.states[state_name] = len(self.drawables) + self.drawables.append(drawable) + + def set_state(self, state_name): + self.state = self.states[state_name] + + +class Button(Clickable, StateDrawable): + + def __init__(self, rect, normal_drawable, down_drawable): + super(Button, self).__init__(rect) + self.add_state('NORMAL', normal_drawable) + self.add_state('DOWN', down_drawable) + self.set_state('NORMAL') + + def on_mouse_down(self, pos): + self.set_state('DOWN') + + def on_mouse_up(self, pos): + self.set_state('NORMAL') + self.on_click() + + def on_mouse_cancel(self): + self.set_state('NORMAL') + + +class TextButton(Button): + + def __init__(self, rect, normal_drawable, down_drawable, text): + super(TextButton, self).__init__(rect, normal_drawable, down_drawable) + self.surface = Surface((rect[2], rect[3])) + self.text = text + font_large.set_bold(True) + self.text_surface = font_large.render(self.text, True, (128, 128, 128)) + shadow = font_large.render(self.text, True, (0, 0, 0)) + font_large.set_bold(False) + self.text_surface.blit(shadow, (-2, -2)) + size = font_large.size(self.text) + self.text_offset = ((rect[2] - size[0]) / 2, (rect[3] - size[1]) / 2) + + def draw(self, surface): + self.surface.fill((0, 0, 0, 0)) + super(TextButton, self).draw(self.surface) + self.surface.blit(self.text_surface, self.text_offset) + surface.blit(self.surface, self.rect) diff -r efc4f90cfd63 -r 0e178b20e3ff gamelib/main.py --- a/gamelib/main.py Mon May 07 00:18:16 2012 +0200 +++ b/gamelib/main.py Mon May 07 00:27:59 2012 +0200 @@ -5,10 +5,58 @@ Feel free to put all your game code here, or in other modules in this "gamelib" package. ''' +import pygame +from pygame.locals import MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION, QUIT +from pygame.time import Clock -import data +from gamelib.gui_base import Window +from gamelib.gui import BigButton + + +pygame.init() + +FPS = 30 + +GAME_IS_RUNNING = True + +WINDOW_STACK = [] + +# input variables +MOUSE_DOWN = False def main(): - print "Hello from your game's main()" - print data.load('sample.txt').read() + clock = Clock() + screen = pygame.display.set_mode((800, 600)) + window = Window(screen) + window.background_colour = (0, 0, 0) + button1 = BigButton(((800 - 128) / 2, 200), 'Start') + window.add_child(button1) + WINDOW_STACK.append(window) + while GAME_IS_RUNNING: + process_input() + draw(screen) + clock.tick(FPS) + + +def draw(screen): + for view in WINDOW_STACK: + view.draw(screen) + pygame.display.flip() + + +def process_input(): + global MOUSE_DOWN + global GAME_IS_RUNNING + for event in pygame.event.get(): + if MOUSE_DOWN: + if event.type == MOUSEBUTTONUP: + MOUSE_DOWN = False + WINDOW_STACK[len(WINDOW_STACK) - 1].on_mouse_up(event.pos) + elif event.type == MOUSEMOTION: + WINDOW_STACK[len(WINDOW_STACK) - 1].on_mouse_move(event.pos) + elif not MOUSE_DOWN and event.type == MOUSEBUTTONDOWN: + MOUSE_DOWN = True + WINDOW_STACK[len(WINDOW_STACK) - 1].on_mouse_down(event.pos) + elif event.type == QUIT: + GAME_IS_RUNNING = False