Mercurial > boomslang
diff pyntnclick/gamescreen.py @ 548:ded4324b236e pyntnclick
Moved stuff around, broke everything.
author | Jeremy Thurgood <firxen@gmail.com> |
---|---|
date | Sat, 11 Feb 2012 13:10:18 +0200 |
parents | gamelib/gamescreen.py@a6f9b6edb6c7 |
children | 38fb04728ac5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyntnclick/gamescreen.py Sat Feb 11 13:10:18 2012 +0200 @@ -0,0 +1,261 @@ +# gamescreen.py +# Copyright Boomslang team, 2010 (see COPYING File) +# Main menu for the game + +from albow.controls import Widget +from albow.layout import Row +from albow.palette_view import PaletteView +from albow.screen import Screen +from pygame import Rect, mouse +from pygame.color import Color + +from constants import SCREEN, BUTTON_SIZE, SCENE_SIZE, LEAVE +from cursor import CursorWidget +from state import initial_state, handle_result +from widgets import (MessageDialog, BoomButton, HandButton, PopupMenu, + PopupMenuButton) + + +class InventoryView(PaletteView): + + sel_color = Color("yellow") + sel_width = 2 + + def __init__(self, screen): + PaletteView.__init__(self, (BUTTON_SIZE, BUTTON_SIZE), 1, 6, + scrolling=True) + self.screen = screen + self.state = screen.state + self.state_widget = screen.state_widget + + def num_items(self): + return len(self.state.inventory) + + def draw_item(self, surface, item_no, rect): + item_image = self.state.inventory[item_no].get_inventory_image() + surface.blit(item_image, rect, None) + + def click_item(self, item_no, event): + item = self.state.inventory[item_no] + if self.item_is_selected(item_no): + self.unselect() + elif item.is_interactive(self.state.tool): + result = item.interact(self.state.tool) + handle_result(result, self.state_widget) + else: + self.state.set_tool(self.state.inventory[item_no]) + + def mouse_down(self, event): + if event.button != 1: + self.state.cancel_doodah(self.screen) + else: + PaletteView.mouse_down(self, event) + + def item_is_selected(self, item_no): + return self.state.tool is self.state.inventory[item_no] + + def unselect(self): + self.state.set_tool(None) + + +class StateWidget(Widget): + + def __init__(self, screen): + Widget.__init__(self, Rect(0, 0, SCENE_SIZE[0], SCENE_SIZE[1])) + self.screen = screen + self.state = screen.state + self.detail = DetailWindow(screen) + + def draw(self, surface): + if self.state.previous_scene and self.state.do_check == LEAVE: + # We still need to handle leave events, so still display the scene + self.state.previous_scene.draw(surface, self) + else: + self.state.current_scene.draw(surface, self) + + def mouse_down(self, event): + self.mouse_move(event) + if event.button != 1: # We have a right/middle click + self.state.cancel_doodah(self.screen) + elif self.subwidgets: + self.clear_detail() + self._mouse_move(event.pos) + else: + result = self.state.interact(event.pos) + handle_result(result, self) + + def animate(self): + if self.state.animate(): + # queue a redraw + self.invalidate() + # We do this here so we can get enter and leave events regardless + # of what happens + result = self.state.check_enter_leave(self.screen) + handle_result(result, self) + + def mouse_move(self, event): + self.state.highlight_override = False + if not self.subwidgets: + self._mouse_move(event.pos) + + def _mouse_move(self, pos): + self.state.highlight_override = False + self.state.current_scene.mouse_move(pos) + self.state.old_pos = pos + + def show_message(self, message, style=None): + # Display the message as a modal dialog + MessageDialog(self.screen, message, 60, style=style).present() + # queue a redraw to show updated state + self.invalidate() + # The cursor could have gone anywhere + if self.subwidgets: + self.subwidgets[0]._mouse_move(mouse.get_pos()) + else: + self._mouse_move(mouse.get_pos()) + + def show_detail(self, detail): + self.clear_detail() + detail_obj = self.state.set_current_detail(detail) + self.detail.set_image_rect(Rect((0, 0), detail_obj.get_detail_size())) + self.add_centered(self.detail) + self.state.do_enter_detail() + + def clear_detail(self): + """Hide the detail view""" + if self.state.current_detail is not None: + self.remove(self.detail) + self.state.do_leave_detail() + self.state.set_current_detail(None) + self._mouse_move(mouse.get_pos()) + + def end_game(self): + self.screen.running = False + self.screen.shell.show_screen(self.screen.shell.end_screen) + + +class DetailWindow(Widget): + def __init__(self, screen): + Widget.__init__(self) + self.image_rect = None + self.screen = screen + self.state = screen.state + self.border_width = 5 + self.border_color = (0, 0, 0) + # parent only gets set when we get added to the scene + self.close = BoomButton('Close', self.close_but, screen) + self.add(self.close) + + def close_but(self): + self.parent.clear_detail() + + def end_game(self): + self.parent.end_game() + + def set_image_rect(self, rect): + bw = self.border_width + self.image_rect = rect + self.image_rect.topleft = (bw, bw) + self.set_rect(rect.inflate(bw * 2, bw * 2)) + self.close.rect.midbottom = rect.midbottom + + def draw(self, surface): + scene_surface = self.get_root().surface.subsurface(self.parent.rect) + overlay = scene_surface.convert_alpha() + overlay.fill(Color(0, 0, 0, 191)) + scene_surface.blit(overlay, (0, 0)) + self.state.current_detail.draw( + surface.subsurface(self.image_rect), self) + + def mouse_down(self, event): + self.mouse_move(event) + if event.button != 1: # We have a right/middle click + self.state.cancel_doodah(self.screen) + else: + result = self.state.interact_detail( + self.global_to_local(event.pos)) + handle_result(result, self) + + def mouse_move(self, event): + self._mouse_move(event.pos) + + def _mouse_move(self, pos): + self.state.highlight_override = False + self.state.current_detail.mouse_move(self.global_to_local(pos)) + + def show_message(self, message, style=None): + self.parent.show_message(message, style) + self.invalidate() + + +class ToolBar(Row): + def __init__(self, items): + for item in items: + item.height = BUTTON_SIZE + Row.__init__(self, items, spacing=0, width=SCREEN[0]) + self.bg_color = (31, 31, 31) + + def draw(self, surface): + surface.fill(self.bg_color) + Row.draw(self, surface) + + +class GameScreen(Screen, CursorWidget): + def __init__(self, shell): + CursorWidget.__init__(self, self) + Screen.__init__(self, shell) + self.running = False + + def _clear_all(self): + for widget in self.subwidgets[:]: + self.remove(widget) + + def start_game(self): + self._clear_all() + self.state = initial_state() + self.state_widget = StateWidget(self) + self.add(self.state_widget) + + self.popup_menu = PopupMenu(self) + self.menubutton = PopupMenuButton('Menu', + action=self.popup_menu.show_menu) + + self.handbutton = HandButton(action=self.hand_pressed) + + self.inventory = InventoryView(self) + + self.toolbar = ToolBar([ + self.menubutton, + self.handbutton, + self.inventory, + ]) + self.toolbar.bottomleft = self.bottomleft + self.add(self.toolbar) + + self.running = True + + def enter_screen(self): + CursorWidget.enter_screen(self) + + def leave_screen(self): + CursorWidget.leave_screen(self) + + # Albow uses magic method names (command + '_cmd'). Yay. + # Albow's search order means they need to be defined here, not in + # PopMenu, which is annoying. + def hide_cmd(self): + # This option does nothing, but the method needs to exist for albow + return + + def main_menu_cmd(self): + self.shell.show_screen(self.shell.menu_screen) + + def quit_cmd(self): + self.shell.quit() + + def hand_pressed(self): + self.inventory.unselect() + + def begin_frame(self): + if self.running: + self.state_widget.animate()