Mercurial > sypikslang
view gamelib/gamegui.py @ 143:821ecb98e888
some icons and toggle button
author | Rizmari Versfeld <rizziepit@gmail.com> |
---|---|
date | Fri, 11 May 2012 03:13:22 +0200 |
parents | 07be37129447 |
children | 53277724645b |
line wrap: on
line source
# -*- coding: utf-8 -*- # vim:fileencoding=utf-8 ai ts=4 sts=4 et sw=4 """Gui for the actual game""" from pygame import image try: import simplejson json = simplejson except ImportError: import json from gamelib.data import filepath from gamelib.game_base import get_save_filename from gamelib.gui_base import (Window, TextLabel, TextBox, font_small, font_medium, font_large) from gamelib.gui import BigButton, ImageDrawable from gamelib.engine import PopWindow, AddWindow, GameOver from gamelib.constants import WIDTH, HEIGHT, FAILURE, SUCCESS, GAME_WIN, INFO from gamelib.gamestate import Game def _lookup_reputation(rep): """Turn reputation in a nice string""" if rep < 0: return 'Mindless Thug' if rep < 10: return 'Fringe Lunatic' if rep < 100: return 'Mad Scientist' return 'Major Threat to World Peace' class PopWindowButton(BigButton): def __init__(self, pos, text): super(PopWindowButton, self).__init__(pos, text) def on_click(self): PopWindow.post() class ExitGameButton(PopWindowButton): def __init__(self): super(ExitGameButton, self).__init__((WIDTH - 128, HEIGHT - 60), 'Exit') class EndTurnButton(BigButton): def __init__(self, parent): super(EndTurnButton, self).__init__(((WIDTH - 128), 10), 'End Turn') self.parent = parent def on_click(self): self.parent.end_turn() class NextTurnButton(PopWindowButton): def __init__(self): super(NextTurnButton, self).__init__(((WIDTH - 128), 10), 'Next Turn') class DoneButton(PopWindowButton): def __init__(self): super(DoneButton, self).__init__(((WIDTH - 128), 10), 'Done') class ResetButton(BigButton): def __init__(self, parent): super(ResetButton, self).__init__((10, 10), 'Reset points') self.parent = parent def on_click(self): self.parent.do_reset() class SwitchWinButton(BigButton): def __init__(self, pos, text, new_window): super(SwitchWinButton, self).__init__(pos, text) self.new_window = new_window def on_click(self): PopWindow.post() # Refresh state self.new_window.update() AddWindow.post(self.new_window) class ScienceWidget(BigButton): WIDTH = 200 BG_IMAGE_NORMAL = image.load(filepath('images/science_normal.png')) BG_IMAGE_DOWN = image.load(filepath('images/science_down.png')) def __init__(self, science, pos, parent): self.science = science self.points = 0 self.parent = parent super(ScienceWidget, self).__init__(pos, '%s: %d' % (science.NAME, science.points), font_small) def on_click(self): if (self.parent.game.get_available_points() > 0 and self.science.can_spend(self.parent.game.lab, self.points + 1)): self.points += 1 self.parent.game.cur_allocation.append(self.science) self.parent.update_labels() self.set_text() def set_text(self): if self.points > 0: self.text = '%s: %d + %d' % (self.science.NAME, self.science.points, self.points) else: self.text = '%s: %d' % (self.science.NAME, self.science.points) self._draw_text() def reset(self): while self.points > 0: self.parent.game.cur_allocation.remove(self.science) self.points -= 1 self.set_text() self.parent.update_labels() def restore_selection(self, old_selection): points = old_selection.count(self.science) # We skip things we cannot allocate enoigh points to (temp points # boosts, etc.) or we cannot currently develop further if (points != self.points and points <= self.parent.game.get_available_points() and self.science.can_spend(self.parent.game.lab, self.points + points)): self.points = points self.parent.game.cur_allocation.extend([self.science] * points) self.parent.update_labels() self.set_text() class MissionWidget(BigButton): WIDTH = 200 BG_IMAGE_NORMAL = image.load(filepath('images/science_normal.png')) BG_IMAGE_DOWN = image.load(filepath('images/science_down.png')) BG_IMAGE_SELECTED = image.load(filepath('images/mission_selected.png')) def __init__(self, mission, pos, parent): self.mission = mission self.parent = parent self.game = self.parent.game self.minions = 0 super(MissionWidget, self).__init__(pos, '%s' % mission.NAME, font_small) selected = ImageDrawable((0, 0, self.WIDTH, self.HEIGHT), self.BG_IMAGE_SELECTED) self.add_state('SELECTED', selected) self.mode = 'NORMAL' self.equipment = [] def on_mouse_cancel(self, pos): self.set_state(self.mode) def on_mouse_up(self, pos): self.set_state(self.mode) self.on_click() def on_click(self): if self.mode == 'SELECTED': # unselect mission self.reset() elif self.mission.can_attempt(self.game): # select mission and equipment self.mode = 'SELECTED' self.set_state('SELECTED') self.minions = self.mission.MINIONS_REQUIRED self.game.minions -= self.minions self.parent.update_labels() equip = EquipWindow(self.parent.screen, self.mission, self.game, self) AddWindow.post(equip) def selected(self): return self.mode == 'SELECTED' def get_equipment(self): return self.equipment def reset(self): for equip in self.equipment: # Release funds self.game.money += equip.COST self.game.minions += self.minions self.minions = 0 self.parent.update() self.equipment = [] self.mode = 'NORMAL' self.set_state('NORMAL') class EquipWidget(BigButton): WIDTH = 200 BG_IMAGE_NORMAL = image.load(filepath('images/science_normal.png')) BG_IMAGE_DOWN = image.load(filepath('images/science_down.png')) BG_IMAGE_UNAVAILABLE = image.load(filepath('images/equip_grey.png')) def __init__(self, equip, pos, parent, copies, available): self.equip = equip self.parent = parent self.available = available super(EquipWidget, self).__init__(pos, '[%s : %d] - %d (x %d)' % (equip.NAME, equip.points, equip.COST, copies), font_small) if not self.available: unavailable = ImageDrawable((0, 0, self.WIDTH, self.HEIGHT), self.BG_IMAGE_UNAVAILABLE) # Override the default self.add_state('NORMAL', unavailable) self.set_state('NORMAL') self.equipment = [] def on_mouse_down(self, pos): if self.available: super(EquipWidget, self).on_mouse_down(pos) def on_mouse_up(self, pos): if self.available: super(EquipWidget, self).on_mouse_up(pos) def on_click(self): self.parent.buy(self.equip) class ValueLabel(TextLabel): def __init__(self, pos, description): self.description = description rect = (pos[0], pos[1], 300, 50) super(ValueLabel, self).__init__(rect, '%s : 0' % description, font_medium, (255, 255, 0)) def set_value(self, value): self.text = '%s : %s' % (self.description, value) self._draw_text() class EquipWindow(Window): def __init__(self, screen, mission, game, parent): super(EquipWindow, self).__init__(screen) donebut = DoneButton() self.add_child(donebut) reset = ResetButton(self) self.add_child(reset) title = TextLabel((200, 20, 400, 50), "Choose equipment for %s" % mission.NAME, font_medium, (255, 255, 255)) self.add_child(title) description = TextBox((10, 70, 790, 20), mission.LONG_DESCRIPTION, font_medium, (255, 255, 255)) self.add_child(description) self.parent = parent self.game = game self.money = ValueLabel((10, description.rect.height + 75), 'Money') self.money.set_value(self.game.money) self.add_child(self.money) self._equip = [] self._make_equip_widgets() def _make_equip_widgets(self): for widget in self._equip: self.remove_child(widget) self._equip = [] x = 0 y = 150 available = self.game.get_available_equipment() for equip in self.game.get_all_equipment(): copies = self.parent.equipment.count(equip) widget = EquipWidget(equip, (x, y), self, copies, equip in available) self._equip.append(widget) self.add_child(widget) x += 200 if x >= WIDTH: x = 0 y += 100 def buy(self, equip): self.game.money -= equip.COST self.money.set_value(self.game.money) self.parent.equipment.append(equip) self.parent.parent.update() self._make_equip_widgets() def do_reset(self): for equip in self.parent.equipment: # Release funds self.game.money += equip.COST self.money.set_value(self.game.money) self.parent.equipment = [] self.parent.parent.update() self._make_equip_widgets() class ResultsWindow(Window): message_colours = { INFO: (60, 60, 255), FAILURE: (255, 60, 60), SUCCESS: (60, 255, 60), } def __init__(self, screen, messages, turn): super(ResultsWindow, self).__init__(screen) nextbut = NextTurnButton() self.add_child(nextbut) title = TextLabel((200, 20, 400, 50), "Results for turn %d" % turn, font_medium, (255, 255, 255)) self.add_child(title) self.is_game_over = False if not messages: results = TextBox((200, 200, 400, 50), "Nothing of interest happened", font_medium, (255, 255, 255)) self.add_child(results) else: y = 200 for msg_type, msg, loot in messages: # FIXME: Better widgets if msg_type == GAME_WIN: self._make_win_screen(turn, msg) self.is_game_over = True break colour = self.message_colours.get(msg_type, (255, 255, 255)) y = self.display_message(y, msg, loot, colour) def display_message(self, y, msg, loot, colour, font=font_medium): text = TextBox((50, y, 700, 25), msg, font, colour) y += text.rect.height + 5 self.add_child(text) for kind, value in loot.items(): y += self.display_loot_item(y, kind, value) return y + 5 def display_loot_item(self, y, kind, value): if hasattr(value, 'NAME'): value = value.NAME msg = "* %s: %s" % (kind, value) text = TextBox((80, y, 670, 25), msg, font_medium, (255, 255, 60)) self.add_child(text) return text.rect.height + 5 def _make_win_screen(self, turn, msg): # Clear existing widgets, and turn this into a won screen for child in self.children[:]: self.remove_child(child) exitbut = ExitGameButton() self.add_child(exitbut) title = TextLabel((200, 20, 400, 50), "Results for turn %d" % turn, font_medium, (255, 255, 255)) self.add_child(title) won = TextBox((200, 200, 400, 50), "You've succeeded in your quest", font_large, (255, 255, 255)) self.add_child(won) won = TextBox((200, 250, 400, 50), msg, font_large, (255, 255, 255)) self.add_child(won) class GameStateWindow(Window): """Base class for windows that show a lot of game state info""" def __init__(self, screen, game): super(GameStateWindow, self).__init__(screen) self.game = game self.screen = screen exitbut = ExitGameButton() self.add_child(exitbut) end_turn = EndTurnButton(self) self.add_child(end_turn) reset = ResetButton(self) self.add_child(reset) self.points = ValueLabel((10, 75), 'Available Human Resources') self.add_child(self.points) self.minions = ValueLabel((310, 75), 'Minions available: ') self.add_child(self.minions) self.money = ValueLabel((510, 75), 'Money') self.add_child(self.money) self.milestone = ValueLabel((10, 95), 'Currently taken over') self.add_child(self.milestone) self.reputation = ValueLabel((310, 95), 'Reputation') self.add_child(self.reputation) def update_labels(self): self.points.set_value(self.game.get_available_points()) self.money.set_value(self.game.money) self.minions.set_value(self.game.minions) self.milestone.set_value(self.game.milestone) self.reputation.set_value(_lookup_reputation(self.game.reputation)) class ActivityWindow(GameStateWindow): def __init__(self, screen, lab, develop): super(ActivityWindow, self).__init__(screen, lab.game) self.lab = lab self.develop = develop labbut = SwitchWinButton((150, 10), 'Research', lab) self.add_child(labbut) devbut = SwitchWinButton((300, 10), 'Development', develop) self.add_child(devbut) self.update_labels() self._missions = [] self._make_widgets() def _make_widgets(self): for widget in self._missions: self.remove_child(widget) self._missions = [] x = 0 y = 150 for mission in self.game.get_available_missions(): widget = MissionWidget(mission, (x, y), self) self._missions.append(widget) self.add_child(widget) x += 200 if x >= WIDTH: x = 0 y += 100 def end_turn(self): # Drop back to the research screen PopWindow.post() self.lab.update() AddWindow.post(self.lab) self.lab.end_turn() def update_widgets(self): self._make_widgets() def update(self): self.update_labels() def do_reset(self): self.lab.reset() self.develop.reset() self.reset() def get_mission_list(self): selected_missions = [] for widget in self._missions: if widget.selected(): equipment = widget.get_equipment() mission = widget.mission selected_missions.append((mission, equipment)) return selected_missions def reset(self): for widget in self._missions: widget.reset() self.update_labels() class DevelopmentWindow(GameStateWindow): """Window for handling schematics research""" def __init__(self, screen, lab): super(DevelopmentWindow, self).__init__(screen, lab.game) self.lab = lab labbut = SwitchWinButton((150, 10), 'Research', lab) self.add_child(labbut) self.activity = None self.update_labels() self._sciences = [] self._make_science_widgets() def set_activity_window(self, activity): # Oh, what tangled webs we weave if not self.activity: self.activity = activity actbut = SwitchWinButton((300, 10), 'Activities', activity) self.add_child(actbut) def _make_science_widgets(self): for widget in self._sciences: self.remove_child(widget) self._sciences = [] x = 0 y = 150 for science in self.game.lab.science: if science.SCIENCE_TYPE == 'schematic': widget = ScienceWidget(science, (x, y), self) self.add_child(widget) self._sciences.append(widget) x += 200 if x >= WIDTH: x = 0 y += 100 def end_turn(self): # Drop back to the research screen PopWindow.post() self.lab.update() AddWindow.post(self.lab) self.lab.end_turn() def update_widgets(self): self._make_science_widgets() self.update_labels() def update(self): self.update_labels() def do_reset(self): self.reset() self.lab.reset() self.activity.reset() def reset(self): for widget in self._sciences: widget.reset() def restore_selection(self, old_selection): for widget in self._sciences: widget.restore_selection(old_selection) class LabWindow(GameStateWindow): """Window for the research lab""" def __init__(self, screen, game_dict): self.game = Game(game_dict) super(LabWindow, self).__init__(screen, self.game) self.autosave = get_save_filename() # Ensure we setup everything with the correct state set self.game.start_turn() self.develop = DevelopmentWindow(screen, self) self.activity = ActivityWindow(screen, self, self.develop) self.develop.set_activity_window(self.activity) devbut = SwitchWinButton((150, 10), 'Development', self.develop) self.add_child(devbut) actbut = SwitchWinButton((300, 10), 'Activities', self.activity) self.add_child(actbut) self._sciences = [] # Setup for the first turn self.update_labels() self._make_science_widgets() def _make_science_widgets(self): # FIXME: Horrible hackery for widget in self._sciences: self.remove_child(widget) self._sciences = [] x = 0 y = 150 for science in self.game.lab.science: if science.SCIENCE_TYPE == 'research': widget = ScienceWidget(science, (x, y), self) self.add_child(widget) self._sciences.append(widget) x += 200 if x >= WIDTH: x = 0 y += 100 def update_widgets(self): self._make_science_widgets() def restore_selection(self, old_selection): for widget in self._sciences: widget.restore_selection(old_selection) def end_turn(self): self.game.cur_missions = self.activity.get_mission_list() old_allocation = self.game.cur_allocation messages = self.game.end_turn() results = ResultsWindow(self.screen, messages, self.game.turn) if results.is_game_over: PopWindow.post() GameOver.post(results) return self.save_game() self.game.start_turn() self.update_widgets() self.develop.update_widgets() self.activity.update_widgets() # restore previous allocation self.restore_selection(old_allocation) self.develop.restore_selection(old_allocation) self.update_labels() self.develop.update_labels() AddWindow.post(results) def save_game(self): game_data = self.game.save_data() if self.autosave: # Don't corrupt the savefile if json crashes data = json.dumps(game_data) savefile = open(self.autosave, 'w') savefile.write(data) savefile.close() def update(self): self.update_labels() def do_reset(self): self.reset() self.develop.reset() self.activity.reset() def reset(self): for widget in self._sciences: widget.reset()