def create_shop_menu(items, gold): entries = [] row = [] for i, it in enumerate(items): entry = { 'type': 'item_button', 'item': it, 'price': it.price, 'index': i, 'id': BuyMenu.INTERAC_BUY } row.append(entry) if len(row) == 2: entries.append(row) row = [] if row: entries.append(row) # Gold at end entry = [{ 'type': 'text', 'text': 'Your gold : ' + str(gold), 'font': fonts['ITEM_DESC_FONT'] }] entries.append(entry) return InfoBox("Shop - Buying", BuyMenu, "imgs/interface/PopUpMenu.png", entries, ITEM_MENU_WIDTH, close_button=UNFINAL_ACTION, title_color=ORANGE)
def create_options_menu(): entries = [[ StartScreen.load_parameter_entry("move_speed", "Move speed : ", [{ 'label': 'Slow', 'value': ANIMATION_SPEED // 2 }, { 'label': 'Normal', 'value': ANIMATION_SPEED }, { 'label': 'Fast', 'value': ANIMATION_SPEED * 2 }], OptionsMenu.CHANGE_MOVE_SPEED) ], [ StartScreen.load_parameter_entry( "screen_size", "Screen mode : ", [{ 'label': 'Window', 'value': SCREEN_SIZE // 2 }, { 'label': 'Full', 'value': SCREEN_SIZE }], OptionsMenu.CHANGE_SCREEN_SIZE) ]] for row in entries: for entry in row: entry['type'] = 'parameter_button' return InfoBox("Options", OptionsMenu, "imgs/interface/PopUpMenu.png", entries, START_MENU_WIDTH, close_button=1)
def create_main_menu(initialization_phase, pos): # Transform pos tuple into rect tile = pg.Rect(pos[0], pos[1], 1, 1) entries = [[{ 'name': 'Save', 'id': MainMenu.SAVE }], [{ 'name': 'Suspend', 'id': MainMenu.SUSPEND }]] if initialization_phase: entries.append([{'name': 'Start', 'id': MainMenu.START}]) else: entries.append([{'name': 'End Turn', 'id': MainMenu.END_TURN}]) for row in entries: for entry in row: entry['type'] = 'button' return InfoBox("Main Menu", MainMenu, "imgs/interface/PopUpMenu.png", entries, ACTION_MENU_WIDTH, el_rect_linked=tile)
def create_equipment_menu(equipments): entries = [] body_parts = [['head'], ['body'], ['right_hand', 'left_hand'], ['feet']] for part in body_parts: row = [] for member in part: entry = { 'type': 'item_button', 'item': None, 'index': -1, 'id': EquipmentMenu.INTERAC_EQUIPMENT } for i, eq in enumerate(equipments): if member == eq.body_part: entry = { 'type': 'item_button', 'item': eq, 'index': i, 'id': EquipmentMenu.INTERAC_EQUIPMENT } row.append(entry) entries.append(row) return InfoBox("Equipment", EquipmentMenu, "imgs/interface/PopUpMenu.png", entries, EQUIPMENT_MENU_WIDTH, close_button=UNFINAL_ACTION)
def create_trade_item_menu(item_button_pos, item, players): entries = [[{ 'name': 'Info', 'id': ItemMenu.INFO_ITEM }], [{ 'name': 'Trade', 'id': ItemMenu.TRADE_ITEM, 'args': players }]] formatted_item_name = item.get_formatted_name() for row in entries: for entry in row: entry['type'] = 'button' item_rect = pg.Rect(item_button_pos[0] - 20, item_button_pos[1], ITEM_BUTTON_SIZE[0], ITEM_BUTTON_SIZE[1]) return InfoBox(formatted_item_name, ItemMenu, "imgs/interface/PopUpMenu.png", entries, ACTION_MENU_WIDTH, el_rect_linked=item_rect, close_button=UNFINAL_ACTION)
def create_item_menu(item_button_pos, item, is_equipped=False): entries = [[{ 'name': 'Info', 'id': ItemMenu.INFO_ITEM }], [{ 'name': 'Throw', 'id': ItemMenu.THROW_ITEM }]] formatted_item_name = item.get_formatted_name() if isinstance(item, Consumable): entries.insert(0, [{'name': 'Use', 'id': ItemMenu.USE_ITEM}]) elif isinstance(item, Equipment): if is_equipped: entries.insert(0, [{ 'name': 'Unequip', 'id': ItemMenu.UNEQUIP_ITEM }]) else: entries.insert(0, [{'name': 'Equip', 'id': ItemMenu.EQUIP_ITEM}]) for row in entries: for entry in row: entry['type'] = 'button' item_rect = pg.Rect(item_button_pos[0] - 20, item_button_pos[1], ITEM_BUTTON_SIZE[0], ITEM_BUTTON_SIZE[1]) return InfoBox(formatted_item_name, ItemMenu, "imgs/interface/PopUpMenu.png", entries, ACTION_MENU_WIDTH, el_rect_linked=item_rect, close_button=UNFINAL_ACTION)
def create_reward_menu(mission): entries = [[{ 'type': 'text', 'text': 'Congratulations ! Objective has been completed !', 'font': fonts['ITEM_DESC_FONT'] }]] if mission.gold: entries.append([{ 'type': 'text', 'text': 'Earned gold : ' + str(mission.gold) + ' (all characters)' }]) for item in mission.items: entries.append([{ 'type': 'text', 'text': 'Earned item : ' + str(item) }]) return InfoBox(mission.desc, "", "imgs/interface/PopUpMenu.png", entries, REWARD_MENU_WIDTH, close_button=UNFINAL_ACTION)
def create_item_desc_menu(item): item_title = str(item) entries = [[{ 'type': 'text', 'text': item.desc, 'font': fonts['ITEM_DESC_FONT'], 'margin': (20, 0, 20, 0) }]] if isinstance(item, Equipment): if item.restrictions != {}: entries.append( create_item_desc_stat('RESERVED TO', item.get_formatted_restrictions())) if item.atk > 0: entries.append(create_item_desc_stat('POWER', str(item.atk))) if item.defense > 0: entries.append(create_item_desc_stat('DEFENSE', str(item.defense))) if item.res > 0: entries.append(create_item_desc_stat('MAGICAL RES', str(item.res))) if isinstance(item, Weapon): # Compute reach reach_txt = "" for nb in item.reach: reach_txt += str(nb) + ', ' reach_txt = reach_txt[:len(reach_txt) - 2] entries.append( create_item_desc_stat('TYPE OF DAMAGE', str(item.attack_kind.value))) entries.append(create_item_desc_stat('REACH', reach_txt)) for possible_effect in item.effects: entries.append( create_item_desc_stat( 'EFFECT', possible_effect['effect'].get_formatted_name() + ' (' + str(possible_effect['probability']) + '%)')) if isinstance(item, Shield): entries.append( create_item_desc_stat('PARRY RATE', str(item.parry) + '%')) if isinstance(item, Weapon) or isinstance(item, Shield): entries.append( create_item_desc_stat( 'DURABILITY', str(item.durability) + ' / ' + str(item.durability_max))) entries.append(create_item_desc_stat('WEIGHT', str(item.weight))) elif isinstance(item, Consumable): for eff in item.effects: entries.append( create_item_desc_stat('EFFECT', eff.get_formatted_desc())) return InfoBox(item_title, "", "imgs/interface/PopUpMenu.png", entries, ITEM_INFO_MENU_WIDTH, close_button=UNFINAL_ACTION)
def create_menu(): entries = [[{'name': 'New game', 'id': StartMenu.NEW_GAME}], [{'name': 'Load game', 'id': StartMenu.LOAD_GAME}], [{'name': 'Options', 'id': StartMenu.OPTIONS}], [{'name': 'Exit game', 'id': StartMenu.EXIT}]] for row in entries: for entry in row: entry['type'] = 'button' return InfoBox("In the name of the Five Cats", StartMenu, "imgs/interface/PopUpMenu.png", entries, START_MENU_WIDTH)
def load_game(self): try: save = open("saves/main_save.xml", "r") # Test if there is a current saved game if save: tree_root = etree.parse("saves/main_save.xml").getroot() index = tree_root.find("level/index").text.strip() level_name = 'maps/level_' + index + '/' game_status = tree_root.find("level/phase").text.strip() turn_nb = 0 if game_status != 'I': turn_nb = int(tree_root.find("level/turn").text.strip()) # Load level with current game status, foes states, and team self.level_id = int(index) level = Level(level_name, self.level_id, game_status, turn_nb, tree_root.find("level/entities")) self.play(level) save.close() return except FileNotFoundError: # No saved game self.background_menus.append([self.active_menu, True]) name = "Load Game" entries = [[{ 'type': 'text', 'text': "No saved game.", 'font': fonts['MENU_SUB_TITLE_FONT'] }]] width = self.screen.get_width() // 2 self.active_menu = InfoBox(name, "", "imgs/interface/PopUpMenu.png", entries, width, close_button=1)
def create_skill_info_menu(skill): entries = [[{ 'type': 'text', 'text': skill.desc, 'font': fonts['ITEM_DESC_FONT'], 'margin': (20, 0, 20, 0) }], [{ 'type': 'text', 'text': '', 'margin': (0, 0, 10, 0) }]] return InfoBox(skill.formatted_name, "", "imgs/interface/PopUpMenu.png", entries, STATUS_INFO_MENU_WIDTH, close_button=UNFINAL_ACTION)
def create_item_sell_menu(item_button_pos, item): entries = [[{ 'name': 'Sell', 'id': ItemMenu.SELL_ITEM, 'type': 'button' }], [{ 'name': 'Info', 'id': ItemMenu.INFO_ITEM, 'type': 'button' }]] formatted_item_name = str(item) item_rect = pg.Rect(item_button_pos[0] - 20, item_button_pos[1], ITEM_BUTTON_SIZE[0], ITEM_BUTTON_SIZE[1]) return InfoBox(formatted_item_name, ItemMenu, "imgs/interface/PopUpMenu.png", entries, ACTION_MENU_WIDTH, el_rect_linked=item_rect, close_button=UNFINAL_ACTION)
def create_inventory_menu(items, gold, price=False): entries = [] row = [] method_id = SellMenu.INTERAC_SELL if price else InventoryMenu.INTERAC_ITEM for i, it in enumerate(items): entry = { 'type': 'item_button', 'item': it, 'index': i, 'id': method_id } # Test if price should appeared if price and it: entry['price'] = it.price // 2 if it.price != 0 else 0 row.append(entry) if len(row) == 2: entries.append(row) row = [] if row: entries.append(row) # Gold at end entry = [{ 'type': 'text', 'text': 'Your gold : ' + str(gold), 'font': fonts['ITEM_DESC_FONT'] }] entries.append(entry) title = "Shop - Selling" if price else "Inventory" menu_id = SellMenu if price else InventoryMenu title_color = ORANGE if price else WHITE return InfoBox(title, menu_id, "imgs/interface/PopUpMenu.png", entries, ITEM_MENU_WIDTH, close_button=UNFINAL_ACTION, title_color=title_color)
def create_item_shop_menu(item_button_pos, item, price): entries = [[{ 'name': 'Buy', 'id': ItemMenu.BUY_ITEM, 'type': 'button', 'args': [price] }], [{ 'name': 'Info', 'id': ItemMenu.INFO_ITEM, 'type': 'button' }]] formatted_item_name = item.get_formatted_name() item_rect = pg.Rect(item_button_pos[0] - 20, item_button_pos[1], ITEM_BUTTON_SIZE[0], ITEM_BUTTON_SIZE[1]) return InfoBox(formatted_item_name, ItemMenu, "imgs/interface/PopUpMenu.png", entries, ACTION_MENU_WIDTH, el_rect_linked=item_rect, close_button=UNFINAL_ACTION)
def create_alteration_info_menu(alteration): turns_left = alteration.get_turns_left() entries = [[{ 'type': 'text', 'text': alteration.desc, 'font': fonts['ITEM_DESC_FONT'], 'margin': (20, 0, 20, 0) }], [{ 'type': 'text', 'text': 'Turns left : ' + str(turns_left), 'font': fonts['ITEM_DESC_FONT'], 'margin': (0, 0, 10, 0), 'color': ORANGE }]] return InfoBox(str(alteration), "", "imgs/interface/PopUpMenu.png", entries, STATUS_INFO_MENU_WIDTH, close_button=UNFINAL_ACTION)
def create_foe_menu(foe): formatted_name = foe.get_formatted_name() entries = [[], [{ 'type': 'text', 'color': WHITE, 'text': 'Level :', 'margin': (10, 0, 0, 0) }, { 'type': 'text', 'text': str(foe.lvl), 'margin': (10, 0, 0, 0) }], [{ 'type': 'text', 'color': WHITE, 'text': 'STATS', 'font': fonts['MENU_SUB_TITLE_FONT'], 'margin': (10, 0, 10, 0) }], [{ 'type': 'text', 'color': WHITE, 'text': 'HP :' }, { 'type': 'text', 'text': str(foe.hp) + ' / ' + str(foe.hp_max), 'color': determine_hp_color(foe.hp, foe.hp_max) }], [{ 'type': 'text', 'color': WHITE, 'text': 'MOVE :' }, { 'type': 'text', 'text': str(foe.max_moves) }], [{ 'type': 'text', 'color': WHITE, 'text': 'ATTACK :' }, { 'type': 'text', 'text': str(foe.strength) }], [{ 'type': 'text', 'color': WHITE, 'text': 'DEFENSE :' }, { 'type': 'text', 'text': str(foe.defense) }], [{ 'type': 'text', 'color': WHITE, 'text': 'MAGICAL RES :' }, { 'type': 'text', 'text': str(foe.res) }], [{ 'type': 'text', 'color': WHITE, 'text': 'ALTERATIONS', 'font': fonts['MENU_SUB_TITLE_FONT'], 'margin': (10, 0, 10, 0) }]] alts = foe.alterations if not alts: entries.append([{'type': 'text', 'color': WHITE, 'text': 'None'}]) for alt in alts: entries.append([{ 'type': 'text_button', 'name': alt.get_formatted_name(), 'id': StatusMenu.INFO_ALTERATION, 'color': WHITE, 'color_hover': TURQUOISE, 'obj': alt }]) return InfoBox(formatted_name, "", "imgs/interface/PopUpMenu.png", entries, STATUS_MENU_WIDTH, close_button=UNFINAL_ACTION)
def create_status_menu(player): entries = [ [{}, { 'type': 'text', 'color': GREEN, 'text': 'Name :', 'font': fonts['ITALIC_ITEM_FONT'] }, { 'type': 'text', 'text': str(player) }, {}], [{}, {}, { 'type': 'text', 'color': DARK_GREEN, 'text': 'SKILLS', 'font': fonts['MENU_SUB_TITLE_FONT'], 'margin': (10, 0, 10, 0) }], [{ 'type': 'text', 'color': GREEN, 'text': 'Class :', 'font': fonts['ITALIC_ITEM_FONT'] }, { 'type': 'text', 'text': player.get_formatted_classes() }], [{ 'type': 'text', 'color': GREEN, 'text': 'Race :', 'font': fonts['ITALIC_ITEM_FONT'] }, { 'type': 'text', 'text': player.get_formatted_race() }], [{ 'type': 'text', 'color': GREEN, 'text': 'Level :', 'font': fonts['ITALIC_ITEM_FONT'] }, { 'type': 'text', 'text': str(player.lvl) }], [{ 'type': 'text', 'color': GOLD, 'text': ' XP :', 'font': fonts['ITALIC_ITEM_FONT'] }, { 'type': 'text', 'text': str(player.xp) + ' / ' + str(player.xp_next_lvl) }], [{ 'type': 'text', 'color': DARK_GREEN, 'text': 'STATS', 'font': fonts['MENU_SUB_TITLE_FONT'], 'margin': (10, 0, 10, 0) }], [{ 'type': 'text', 'color': WHITE, 'text': 'HP :' }, { 'type': 'text', 'text': str(player.hp) + ' / ' + str(player.hp_max), 'color': determine_hp_color(player.hp, player.hp_max) }], [{ 'type': 'text', 'color': WHITE, 'text': 'MOVE :' }, { 'type': 'text', 'text': str(player.max_moves) + player.get_formatted_stat_change('speed') }], [{ 'type': 'text', 'color': WHITE, 'text': 'CONSTITUTION :' }, { 'type': 'text', 'text': str(player.constitution) }], [{ 'type': 'text', 'color': WHITE, 'text': 'ATTACK :' }, { 'type': 'text', 'text': str(player.strength) + player.get_formatted_stat_change('strength') }], [{ 'type': 'text', 'color': WHITE, 'text': 'DEFENSE :' }, { 'type': 'text', 'text': str(player.defense) + player.get_formatted_stat_change('defense') }], [{ 'type': 'text', 'color': WHITE, 'text': 'MAGICAL RES :' }, { 'type': 'text', 'text': str(player.res) + player.get_formatted_stat_change('resistance') }], [{ 'type': 'text', 'color': DARK_GREEN, 'text': 'ALTERATIONS', 'font': fonts['MENU_SUB_TITLE_FONT'], 'margin': (10, 0, 10, 0) }] ] alts = player.alterations if not alts: entries.append([{'type': 'text', 'color': WHITE, 'text': 'None'}]) for alt in alts: entries.append([{ 'type': 'text_button', 'name': alt.get_formatted_name(), 'id': StatusMenu.INFO_ALTERATION, 'color': WHITE, 'color_hover': TURQUOISE, 'obj': alt }]) # Display skills i = 2 for skill in player.skills: skill_displayed = { 'type': 'text_button', 'name': skill.formatted_name, 'id': StatusMenu.INFO_SKILL, 'color': WHITE, 'color_hover': TURQUOISE, 'obj': skill } entries[i].append(skill_displayed) i += 1 for j in range(i, len(entries)): entries[j].append({}) return InfoBox("Status", StatusMenu, "imgs/interface/PopUpMenu.png", entries, STATUS_MENU_WIDTH, close_button=UNFINAL_ACTION)
class StartScreen: def __init__(self, screen): self.screen = screen self.menu_screen = self.screen.copy() # Start screen loop bg_image = pg.image.load('imgs/interface/main_menu_background.jpg').convert_alpha() self.background = pg.transform.scale(bg_image, screen.get_size()) # Creating menu self.active_menu = StartScreen.create_menu() self.background_menus = [] # Memorize if a game is currently being performed self.level = None self.levels = [0, 1] self.level_id = None # Load current saved parameters self.load_options() self.exit = False def load_options(self): # Load current move speed Movable.move_speed = int(self.read_options_file("move_speed")) @staticmethod def create_menu(): entries = [[{'name': 'New game', 'id': StartMenu.NEW_GAME}], [{'name': 'Load game', 'id': StartMenu.LOAD_GAME}], [{'name': 'Options', 'id': StartMenu.OPTIONS}], [{'name': 'Exit game', 'id': StartMenu.EXIT}]] for row in entries: for entry in row: entry['type'] = 'button' return InfoBox("In the name of the Five Cats", StartMenu, "imgs/interface/PopUpMenu.png", entries, START_MENU_WIDTH) @staticmethod def load_parameter_entry(param, formatted_name, values, identifier): val = int(StartScreen.read_options_file(param)) entry = {'name': formatted_name, 'values': values, 'id': identifier, 'current_value_ind': 0} for i in range(len(entry['values'])): if entry['values'][i]['value'] == val: entry['current_value_ind'] = i return entry @staticmethod def create_options_menu(): entries = [[StartScreen.load_parameter_entry("move_speed", "Move speed : ", [{'label': 'Slow', 'value': ANIMATION_SPEED // 2}, {'label': 'Normal', 'value': ANIMATION_SPEED}, {'label': 'Fast', 'value': ANIMATION_SPEED * 2}], OptionsMenu.CHANGE_MOVE_SPEED)]] for row in entries: for entry in row: entry['type'] = 'parameter_button' return InfoBox("Options", OptionsMenu, "imgs/interface/PopUpMenu.png", entries, START_MENU_WIDTH, close_button=1) @staticmethod def modify_options_file(el_to_edit, new_value): tree = etree.parse("saves/options.xml") el = tree.find(".//" + el_to_edit) el.text = str(new_value) tree.write("saves/options.xml") @staticmethod def read_options_file(el_to_read): tree = etree.parse("saves/options.xml").getroot() el = tree.find(".//" + el_to_read) return el.text.strip() def display(self): if self.level: self.screen.fill(BLACK) self.level.display(self.screen) else: self.screen.blit(self.background, (0, 0)) for menu in self.background_menus: if menu[1]: menu[0].display(self.screen) if self.active_menu: self.active_menu.display(self.screen) def play(self, level): # Modify screen self.screen = pg.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) self.level = level def update_state(self): if self.level: status = self.level.update_state() if status is Status.ENDED_VICTORY: self.level_id += 1 if self.level_id in self.levels: team = self.level.passed_players for player in team: # Players are fully restored between level player.healed(player.hp_max) # Reset player's state player.new_turn() self.play(StartScreen.load_level(self.level_id, team)) else: # TODO: Game win dialog? self.screen = pg.display.set_mode((self.menu_screen.get_width(), self.menu_screen.get_height())) self.level = None elif status is Status.ENDED_DEFEAT: self.screen = pg.display.set_mode((self.menu_screen.get_width(), self.menu_screen.get_height())) self.level = None @staticmethod def load_level(level, team): return Level('maps/level_' + str(level) + '/', team, level) def new_game(self): # Init player's team (one character at beginning) team = [LoadFromXMLManager.load_player("john"), LoadFromXMLManager.load_player("archer")] # Init the first level self.level_id = 0 self.play(StartScreen.load_level(self.level_id, team)) def load_game(self): try: save = open("saves/main_save.xml", "r") # Test if there is a current saved game if save: tree_root = etree.parse("saves/main_save.xml").getroot() index = tree_root.find("level/index").text.strip() level_name = 'maps/level_' + index + '/' game_status = tree_root.find("level/phase").text.strip() turn_nb = 0 if game_status != 'I': turn_nb = int(tree_root.find("level/turn").text.strip()) team = [] for player in tree_root.findall("team/player"): name = player.find("name").text.strip() level = int(player.find("level").text.strip()) p_class = player.find("class").text.strip() race = player.find("race").text.strip() gold = int(player.find("gold").text.strip()) exp = int(player.find("exp").text.strip()) hp = int(player.find("hp").text.strip()) strength = int(player.find("strength").text.strip()) defense = int(player.find("def").text.strip()) res = int(player.find("res").text.strip()) move = int(player.find("move").text.strip()) current_hp = int(player.find("currentHp").text.strip()) pos = (int(player.find("position/x").text.strip()) * TILE_SIZE, int(player.find("position/y").text.strip()) * TILE_SIZE) state = player.find("turnFinished").text.strip() inv = [] for it in player.findall("inventory/item"): it_name = it.find("name").text.strip() item = LoadFromXMLManager.parse_item_file(it_name) inv.append(item) equipments = [] for eq in player.findall("equipments/equipment"): eq_name = eq.find("name").text.strip() eq = LoadFromXMLManager.parse_item_file(eq_name) equipments.append(eq) # -- Reading of the XML file for default character's values (i.e. sprites) tree = etree.parse("data/characters.xml").getroot() player_t = tree.xpath(name)[0] sprite = 'imgs/dungeon_crawl/player/' + player_t.find('sprite').text.strip() compl_sprite = player_t.find('complementSprite') if compl_sprite is not None: compl_sprite = 'imgs/dungeon_crawl/player/' + compl_sprite.text.strip() p = Player(name, sprite, hp, defense, res, move, strength, [p_class], equipments, race, gold, level, compl_sprite=compl_sprite) p.earn_xp(exp) p.items = inv p.set_current_hp(current_hp) p.pos = pos if state == "True": p.turn_finished() team.append(p) # Load level with current game status, foes states, and team self.level_id = int(index) level = Level(level_name, team, self.level_id, game_status, turn_nb, tree_root.find("level/entities")) self.play(level) save.close() return except FileNotFoundError: # No saved game self.background_menus.append([self.active_menu, True]) name = "Load Game" entries = [[{'type': 'text', 'text': "No saved game.", 'font': fonts['MENU_SUB_TITLE_FONT']}]] width = self.screen.get_width() // 2 self.active_menu = InfoBox(name, "", "imgs/interface/PopUpMenu.png", entries, width, close_button=1) def options_menu(self): self.background_menus.append([self.active_menu, False]) self.active_menu = StartScreen.create_options_menu() def exit_game(self): self.exit = True def main_menu_action(self, method_id, args): # Execute action if method_id is StartMenu.NEW_GAME: self.new_game() elif method_id is StartMenu.LOAD_GAME: self.load_game() elif method_id is StartMenu.OPTIONS: self.options_menu() elif method_id is StartMenu.EXIT: self.exit_game() else: print("Unknown action... : ", str(method_id)) @staticmethod def options_menu_action(method_id, args): # Execute action if method_id is OptionsMenu.CHANGE_MOVE_SPEED: Movable.move_speed = args[2][0] StartScreen.modify_options_file("move_speed", args[2][0]) else: print("Unknown action... : ", method_id) def execute_action(self, menu_type, action): if not action: return method_id = action[0] args = action[1] # Test if the action is a generic one (according to the method_id) # Close menu : Active menu is closed if method_id is GenericActions.CLOSE: self.active_menu = None if self.background_menus: self.active_menu = self.background_menus.pop()[0] return if menu_type is StartMenu: self.main_menu_action(method_id, args) elif menu_type is OptionsMenu: self.options_menu_action(method_id, args) else: print("Unknown menu... : ", str(menu_type)) def motion(self, pos): if self.level is None: self.active_menu.motion(pos) else: self.level.motion(pos) def click(self, button, pos): if self.level is None: if button == 1: self.execute_action(self.active_menu.type, self.active_menu.click(pos)) else: self.level.click(button, pos) return self.exit def button_down(self, button, pos): if self.level is not None: self.level.button_down(button, pos)
def create_status_entity_menu(ent): entries = [[{ 'type': 'text', 'text': 'LEVEL : ' + str(ent.lvl), 'font': fonts['ITEM_DESC_FONT'] }], [{ 'type': 'text', 'text': 'ATTACK', 'font': fonts['MENU_SUB_TITLE_FONT'], 'color': DARK_GREEN, 'margin': (20, 0, 20, 0) }, {}, {}, { 'type': 'text', 'text': 'LOOT', 'font': fonts['MENU_SUB_TITLE_FONT'], 'color': DARK_GREEN, 'margin': (20, 0, 20, 0) } if isinstance(ent, Foe) else {}, {}], [{ 'type': 'text', 'text': 'TYPE :' }, { 'type': 'text', 'text': str(ent.attack_kind.value) }, {}, {}, {}], [{ 'type': 'text', 'text': 'REACH :' }, { 'type': 'text', 'text': ent.get_formatted_reach() }, {}, {}, {}], [{}, {}, {}, {}, {}], [{}, {}, {}, {}, {}], [{ 'type': 'text', 'text': 'STATS', 'font': fonts['MENU_SUB_TITLE_FONT'], 'color': DARK_GREEN, 'margin': (10, 0, 10, 0) }, {}, {}, { 'type': 'text', 'text': 'SKILLS', 'font': fonts['MENU_SUB_TITLE_FONT'], 'color': DARK_GREEN, 'margin': (10, 0, 10, 0) }, {}], [{ 'type': 'text', 'text': 'HP :' }, { 'type': 'text', 'text': str(ent.hp) + ' / ' + str(ent.hp_max), 'color': determine_hp_color(ent.hp, ent.hp_max) }, {}, {}, {}], [{ 'type': 'text', 'text': 'MOVE :' }, { 'type': 'text', 'text': str(ent.max_moves) }, {}, {}, {}], [{ 'type': 'text', 'text': 'ATTACK :' }, { 'type': 'text', 'text': str(ent.strength) }, {}, {}, {}], [{ 'type': 'text', 'text': 'DEFENSE :' }, { 'type': 'text', 'text': str(ent.defense) }, {}, {}, {}], [{ 'type': 'text', 'text': 'MAGICAL RES :' }, { 'type': 'text', 'text': str(ent.res) }, {}, {}, {}], [{ 'type': 'text', 'text': 'ALTERATIONS', 'font': fonts['MENU_SUB_TITLE_FONT'], 'color': DARK_GREEN, 'margin': (10, 0, 10, 0) }]] alts = ent.alterations if not alts: entries.append([{'type': 'text', 'text': 'None'}]) for alt in alts: entries.append([{ 'type': 'text_button', 'name': alt.get_formatted_name(), 'id': StatusMenu.INFO_ALTERATION, 'color': WHITE, 'color_hover': TURQUOISE, 'obj': alt }]) if isinstance(ent, Foe): loot = ent.potential_loot i = 2 for (item, probability) in loot: name = str(item) entries[i][3] = {'type': 'text', 'text': name} entries[i][4] = { 'type': 'text', 'text': ' (' + str(probability * 100) + '%)' } i += 1 # Display skills i = 7 for skill in ent.skills: entries[i][3] = {'type': 'text', 'text': '> ' + skill.formatted_name} i += 1 return InfoBox(str(ent), StatusMenu, "imgs/interface/PopUpMenu.png", entries, FOE_STATUS_MENU_WIDTH, close_button=UNFINAL_ACTION)
def create_trade_menu(first_player, second_player): # Extract data from players items_max = first_player.nb_items_max items_first = list(first_player.items) free_spaces = items_max - len(items_first) items_first += [None] * free_spaces items_max = first_player.nb_items_max items_second = list(second_player.items) free_spaces = items_max - len(items_second) items_second += [None] * free_spaces entries = [] method_id = TradeMenu.INTERAC_ITEM # We assume that first player and second player items lists have the same size and are even for i in range(len(items_first) // 2): row = [] for owner_i, items in enumerate([items_first, items_second]): for j in range(2): entry = { 'type': 'item_button', 'item': items[i * 2 + j], 'index': i, 'subtype': 'trade', 'id': method_id, 'args': [first_player, second_player, owner_i] } row.append(entry) entries.append(row) # Gold at end entry = [{ 'type': 'text', 'text': first_player.get_formatted_name() + '\'s gold : ' + str(first_player.gold), 'font': fonts['ITEM_DESC_FONT'] }, { 'type': 'text', 'text': second_player.get_formatted_name() + '\'s gold : ' + str(second_player.gold), 'font': fonts['ITEM_DESC_FONT'] }] entries.append(entry) title = "Trade" menu_id = TradeMenu title_color = WHITE return InfoBox(title, menu_id, "imgs/interface/PopUpMenu.png", entries, TRADE_MENU_WIDTH, close_button=UNFINAL_ACTION, sep=True, title_color=title_color)
class StartScreen: screen_size = SCREEN_SIZE def __init__(self, screen): self.screen = screen self.menu_screen = self.screen.copy() # Start screen loop bg_image = pg.image.load( 'imgs/interface/main_menu_background.jpg').convert_alpha() self.background = pg.transform.scale(bg_image, screen.get_size()) # Creating menu self.active_menu = StartScreen.create_menu() self.background_menus = [] # Memorize if a game is currently being performed self.level = None self.levels = [0, 1, 2] self.level_id = None # Load current saved parameters self.load_options() self.exit = False def load_options(self): # Load current move speed Movable.move_speed = int(self.read_options_file("move_speed")) StartScreen.screen_size = int(self.read_options_file("screen_size")) @staticmethod def create_menu(): entries = [[{ 'name': 'New game', 'id': StartMenu.NEW_GAME }], [{ 'name': 'Load game', 'id': StartMenu.LOAD_GAME }], [{ 'name': 'Options', 'id': StartMenu.OPTIONS }], [{ 'name': 'Exit game', 'id': StartMenu.EXIT }]] for row in entries: for entry in row: entry['type'] = 'button' return InfoBox("In the name of the Five Cats", StartMenu, "imgs/interface/PopUpMenu.png", entries, START_MENU_WIDTH) @staticmethod def load_parameter_entry(param, formatted_name, values, identifier): val = int(StartScreen.read_options_file(param)) entry = { 'name': formatted_name, 'values': values, 'id': identifier, 'current_value_ind': 0 } for i in range(len(entry['values'])): if entry['values'][i]['value'] == val: entry['current_value_ind'] = i return entry @staticmethod def create_options_menu(): entries = [[ StartScreen.load_parameter_entry("move_speed", "Move speed : ", [{ 'label': 'Slow', 'value': ANIMATION_SPEED // 2 }, { 'label': 'Normal', 'value': ANIMATION_SPEED }, { 'label': 'Fast', 'value': ANIMATION_SPEED * 2 }], OptionsMenu.CHANGE_MOVE_SPEED) ], [ StartScreen.load_parameter_entry( "screen_size", "Screen mode : ", [{ 'label': 'Window', 'value': SCREEN_SIZE // 2 }, { 'label': 'Full', 'value': SCREEN_SIZE }], OptionsMenu.CHANGE_SCREEN_SIZE) ]] for row in entries: for entry in row: entry['type'] = 'parameter_button' return InfoBox("Options", OptionsMenu, "imgs/interface/PopUpMenu.png", entries, START_MENU_WIDTH, close_button=1) @staticmethod def modify_options_file(el_to_edit, new_value): tree = etree.parse("saves/options.xml") el = tree.find(".//" + el_to_edit) el.text = str(new_value) tree.write("saves/options.xml") @staticmethod def read_options_file(el_to_read): tree = etree.parse("saves/options.xml").getroot() el = tree.find(".//" + el_to_read) return el.text.strip() def display(self): if self.level: self.screen.fill(BLACK) self.level.display(self.screen) else: self.screen.blit(self.background, (0, 0)) for menu in self.background_menus: if menu[1]: menu[0].display(self.screen) if self.active_menu: self.active_menu.display(self.screen) def play(self, level): # Modify screen flags = pg.FULLSCREEN if StartScreen.screen_size == 2 else 0 self.screen = pg.display.set_mode((WIN_WIDTH, WIN_HEIGHT), flags) self.level = level def update_state(self): if self.level: status = self.level.update_state() if status is Status.ENDED_VICTORY and (self.level_id + 1) in self.levels: self.level_id += 1 team = self.level.passed_players + self.level.players for player in team: # Players are fully restored between level player.healed(player.hp_max) # Reset player's state player.new_turn() self.play(StartScreen.load_level(self.level_id, team)) elif status is Status.ENDED_VICTORY or status is Status.ENDED_DEFEAT: # TODO: Game win dialog? self.screen = pg.display.set_mode( (MAIN_WIN_WIDTH, MAIN_WIN_HEIGHT)) self.level = None @staticmethod def load_level(level, team=None): if team is None: team = [] return Level('maps/level_' + str(level) + '/', level, players=team) def new_game(self): # Init the first level self.level_id = 0 self.play(StartScreen.load_level(self.level_id)) def load_game(self): try: save = open("saves/main_save.xml", "r") # Test if there is a current saved game if save: tree_root = etree.parse("saves/main_save.xml").getroot() index = tree_root.find("level/index").text.strip() level_name = 'maps/level_' + index + '/' game_status = tree_root.find("level/phase").text.strip() turn_nb = 0 if game_status != 'I': turn_nb = int(tree_root.find("level/turn").text.strip()) # Load level with current game status, foes states, and team self.level_id = int(index) level = Level(level_name, self.level_id, game_status, turn_nb, tree_root.find("level/entities")) self.play(level) save.close() return except FileNotFoundError: # No saved game self.background_menus.append([self.active_menu, True]) name = "Load Game" entries = [[{ 'type': 'text', 'text': "No saved game.", 'font': fonts['MENU_SUB_TITLE_FONT'] }]] width = self.screen.get_width() // 2 self.active_menu = InfoBox(name, "", "imgs/interface/PopUpMenu.png", entries, width, close_button=1) def options_menu(self): self.background_menus.append([self.active_menu, False]) self.active_menu = StartScreen.create_options_menu() def exit_game(self): self.exit = True def main_menu_action(self, method_id, args): # Execute action if method_id is StartMenu.NEW_GAME: self.new_game() elif method_id is StartMenu.LOAD_GAME: self.load_game() elif method_id is StartMenu.OPTIONS: self.options_menu() elif method_id is StartMenu.EXIT: self.exit_game() else: print("Unknown action... : ", str(method_id)) @staticmethod def options_menu_action(method_id, args): # Execute action if method_id is OptionsMenu.CHANGE_MOVE_SPEED: Movable.move_speed = args[2][0] StartScreen.modify_options_file("move_speed", args[2][0]) elif method_id is OptionsMenu.CHANGE_SCREEN_SIZE: StartScreen.screen_size = args[2][0] StartScreen.modify_options_file("screen_size", args[2][0]) else: print("Unknown action... : ", method_id) def execute_action(self, menu_type, action): if not action: return method_id = action[0] args = action[1] # Test if the action is a generic one (according to the method_id) # Close menu : Active menu is closed if method_id is GenericActions.CLOSE: self.active_menu = None if self.background_menus: self.active_menu = self.background_menus.pop()[0] return if menu_type is StartMenu: self.main_menu_action(method_id, args) elif menu_type is OptionsMenu: self.options_menu_action(method_id, args) else: print("Unknown menu... : ", str(menu_type)) def motion(self, pos): if self.level is None: self.active_menu.motion(pos) else: self.level.motion(pos) def click(self, button, pos): if self.level is None: if button == 1: self.execute_action(self.active_menu.type, self.active_menu.click(pos)) else: self.level.click(button, pos) return self.exit def button_down(self, button, pos): if self.level is not None: self.level.button_down(button, pos)
def load_game(self): try: save = open("saves/main_save.xml", "r") # Test if there is a current saved game if save: tree_root = etree.parse("saves/main_save.xml").getroot() level_name = tree_root.find("level/name").text.strip() game_status = tree_root.find("level/phase").text.strip() turn_nb = 0 if game_status != 'I': turn_nb = int(tree_root.find("level/turn").text.strip()) team = [] for player in tree_root.findall("team/player"): name = player.find("name").text.strip() level = int(player.find("level").text.strip()) p_class = player.find("class").text.strip() race = player.find("race").text.strip() gold = int(player.find("gold").text.strip()) exp = int(player.find("exp").text.strip()) hp = int(player.find("hp").text.strip()) strength = int(player.find("strength").text.strip()) defense = int(player.find("defense").text.strip()) res = int(player.find("res").text.strip()) move = int(player.find("move").text.strip()) current_hp = int(player.find("currentHp").text.strip()) pos = (int(player.find("position/x").text.strip()), int(player.find("position/y").text.strip())) state = player.find("turnFinished").text.strip() inv = [] for it in player.findall("inventory/item"): it_name = it.find("name").text.strip() item = Level.parse_item_file(it_name) inv.append(item) equipments = [] for eq in player.findall("equipments/equipment"): eq_name = eq.find("name").text.strip() eq = Level.parse_item_file(eq_name) equipments.append(eq) # -- Reading of the XML file for default character's values (i.e. sprites) tree = etree.parse("data/characters.xml").getroot() player_t = tree.xpath(name)[0] sprite = 'imgs/dungeon_crawl/player/' + player_t.find( 'sprite').text.strip() compl_sprite = player_t.find('complementSprite') if compl_sprite is not None: compl_sprite = 'imgs/dungeon_crawl/player/' + compl_sprite.text.strip( ) p = Player(name, sprite, hp, defense, res, move, strength, [p_class], equipments, race, gold, level, compl_sprite=compl_sprite) p.earn_xp(exp) p.set_items(inv) p.set_current_hp(current_hp) p.set_pos(pos) if state == "True": p.turn_finished() team.append(p) # Load level with current game status, foes states, and team level = Level(level_name, team, game_status, turn_nb, tree_root.find("level/entities")) self.play(level) save.close() return except FileNotFoundError as err: pass # No saved game self.background_menus.append([self.active_menu, True]) name = "Load Game" entries = [[{ 'type': 'text', 'text': "No saved game.", 'font': ITEM_DESC_FONT }]] width = self.screen.get_width() // 2 self.active_menu = InfoBox(name, "", "imgs/interface/PopUpMenu.png", entries, width, close_button=1)
def create_status_menu(player): entries = [[{ 'type': 'text', 'color': GREEN, 'text': 'Name :', 'font': fonts['ITALIC_ITEM_FONT'] }, { 'type': 'text', 'text': player.get_formatted_name() }], [{ 'type': 'text', 'color': GREEN, 'text': 'Class :', 'font': fonts['ITALIC_ITEM_FONT'] }, { 'type': 'text', 'text': player.get_formatted_classes() }], [{ 'type': 'text', 'color': GREEN, 'text': 'Race :', 'font': fonts['ITALIC_ITEM_FONT'] }, { 'type': 'text', 'text': player.get_formatted_race() }], [{ 'type': 'text', 'color': GREEN, 'text': 'Level :', 'font': fonts['ITALIC_ITEM_FONT'] }, { 'type': 'text', 'text': str(player.lvl) }], [{ 'type': 'text', 'color': GOLD, 'text': ' XP :', 'font': fonts['ITALIC_ITEM_FONT'] }, { 'type': 'text', 'text': str(player.xp) + ' / ' + str(player.xp_next_lvl) }], [{ 'type': 'text', 'color': WHITE, 'text': 'STATS', 'font': fonts['MENU_SUB_TITLE_FONT'], 'margin': (10, 0, 10, 0) }], [{ 'type': 'text', 'color': WHITE, 'text': 'HP :' }, { 'type': 'text', 'text': str(player.hp) + ' / ' + str(player.hp_max), 'color': determine_hp_color(player.hp, player.hp_max) }], [{ 'type': 'text', 'color': WHITE, 'text': 'MOVE :' }, { 'type': 'text', 'text': str(player.max_moves) }], [{ 'type': 'text', 'color': WHITE, 'text': 'ATTACK :' }, { 'type': 'text', 'text': str(player.strength) }], [{ 'type': 'text', 'color': WHITE, 'text': 'DEFENSE :' }, { 'type': 'text', 'text': str(player.defense) }], [{ 'type': 'text', 'color': WHITE, 'text': 'MAGICAL RES :' }, { 'type': 'text', 'text': str(player.res) }], [{ 'type': 'text', 'color': WHITE, 'text': 'ALTERATIONS', 'font': fonts['MENU_SUB_TITLE_FONT'], 'margin': (10, 0, 10, 0) }]] alts = player.alterations if not alts: entries.append([{'type': 'text', 'color': WHITE, 'text': 'None'}]) for alt in alts: entries.append([{ 'type': 'text_button', 'name': alt.get_formatted_name(), 'id': StatusMenu.INFO_ALTERATION, 'color': WHITE, 'color_hover': TURQUOISE, 'obj': alt }]) return InfoBox("Status", StatusMenu, "imgs/interface/PopUpMenu.png", entries, STATUS_MENU_WIDTH, close_button=UNFINAL_ACTION)
def create_player_menu(player, buildings, interact_entities, missions, foes): entries = [[{ 'name': 'Inventory', 'id': CharacterMenu.INV }], [{ 'name': 'Equipment', 'id': CharacterMenu.EQUIPMENT }], [{ 'name': 'Status', 'id': CharacterMenu.STATUS }], [{ 'name': 'Wait', 'id': CharacterMenu.WAIT }]] # Options flags chest_option = False portal_option = False fountain_option = False talk_option = False trade_option = False case_pos = (player.pos[0], player.pos[1] - TILE_SIZE) if (0, 0) < case_pos < (MAP_WIDTH, MAP_HEIGHT): for building in buildings: if building.pos == case_pos: entries.insert(0, [{ 'name': 'Visit', 'id': CharacterMenu.VISIT }]) break for ent in interact_entities: if abs(ent.pos[0] - player.pos[0]) + abs(ent.pos[1] - player.pos[1]) == TILE_SIZE: if isinstance(ent, Player): if not trade_option: entries.insert(0, [{ 'name': 'Trade', 'id': CharacterMenu.TRADE }]) trade_option = True elif isinstance(ent, Chest): if not ent.opened and not chest_option: entries.insert(0, [{ 'name': 'Open', 'id': CharacterMenu.OPEN_CHEST }]) chest_option = True elif isinstance(ent, Portal): if not portal_option: entries.insert(0, [{ 'name': 'Use Portal', 'id': CharacterMenu.USE_PORTAL }]) portal_option = True elif isinstance(ent, Fountain): if not fountain_option: entries.insert(0, [{ 'name': 'Drink', 'id': CharacterMenu.DRINK }]) fountain_option = True elif isinstance(ent, Character): if not talk_option: entries.insert(0, [{ 'name': 'Talk', 'id': CharacterMenu.TALK }]) talk_option = True # Check if player is on mission position for mission in missions: if mission.type is MissionType.POSITION: if mission.pos_is_valid(player.pos): entries.insert(0, [{'name': 'Take', 'id': CharacterMenu.TAKE}]) # Check if player could attack something, according to weapon range w_range = [1] if player.get_weapon() is None else player.get_weapon().reach end = False for foe in foes: for reach in w_range: if abs(foe.pos[0] - player.pos[0]) + abs(foe.pos[1] - player.pos[1]) == TILE_SIZE * reach: entries.insert(0, [{ 'name': 'Attack', 'id': CharacterMenu.ATTACK }]) end = True break if end: break for row in entries: for entry in row: entry['type'] = 'button' return InfoBox("Select an action", CharacterMenu, "imgs/interface/PopUpMenu.png", entries, ACTION_MENU_WIDTH, el_rect_linked=player.get_rect())
class StartScreen: def __init__(self, screen): self.screen = screen self.menu_screen = self.screen.copy() # Start screen loop bg_image = pg.image.load( 'imgs/interface/main_menu_background.jpg').convert_alpha() self.background = pg.transform.scale(bg_image, screen.get_size()) # Creating menu self.active_menu = StartScreen.create_menu() self.background_menus = [] # Memorize if a game is currently being performed self.level = None # Load current saved parameters self.load_options() def load_options(self): # Load current move speed Movable.move_speed = int(self.read_options_file("move_speed")) @staticmethod def create_menu(): entries = [[{ 'name': 'New game', 'id': NEW_GAME_ACTION_ID }], [{ 'name': 'Load game', 'id': LOAD_GAME_ACTION_ID }], [{ 'name': 'Options', 'id': OPTIONS_ACTION_ID }], [{ 'name': 'Exit game', 'id': EXIT_ACTION_ID }]] for row in entries: for entry in row: entry['type'] = 'button' return InfoBox("In the name of the Five Cats", START_MENU_ID, "imgs/interface/PopUpMenu.png", entries, START_MENU_WIDTH) @staticmethod def load_parameter_entry(param, formatted_name, values, id): val = int(StartScreen.read_options_file(param)) entry = { 'name': formatted_name, 'values': values, 'id': id, 'current_value_ind': 0 } for i in range(len(entry['values'])): if entry['values'][i]['value'] == val: entry['current_value_ind'] = i return entry @staticmethod def create_options_menu(): entries = [[ StartScreen.load_parameter_entry("move_speed", "Move speed : ", [{ 'label': 'Slow', 'value': ANIMATION_SPEED // 2 }, { 'label': 'Normal', 'value': ANIMATION_SPEED }, { 'label': 'Fast', 'value': ANIMATION_SPEED * 2 }], CHANGE_MOVE_SPEED) ]] for row in entries: for entry in row: entry['type'] = 'parameter_button' return InfoBox("Options", OPTIONS_MENU_ID, "imgs/interface/PopUpMenu.png", entries, START_MENU_WIDTH, close_button=1) @staticmethod def modify_options_file(el_to_edit, new_value): tree = etree.parse("saves/options.xml") el = tree.find(".//" + el_to_edit) el.text = str(new_value) tree.write("saves/options.xml") @staticmethod def read_options_file(el_to_read): tree = etree.parse("saves/options.xml").getroot() el = tree.find(".//" + el_to_read) return el.text.strip() def display(self): if self.level: self.screen.fill(BLACK) self.level.display(self.screen) else: self.screen.blit(self.background, (0, 0)) for menu in self.background_menus: if menu[1]: menu[0].display(self.screen) if self.active_menu: self.active_menu.display(self.screen) def play(self, level): # Modify screen self.screen = pg.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) self.level = level def update_state(self): if self.level: exit = self.level.update_state() if exit: self.screen = pg.display.set_mode( (self.menu_screen.get_width(), self.menu_screen.get_height())) self.level = None def level_is_ended(self): return self.level.is_ended() @staticmethod def init_player(name): # -- Reading of the XML file tree = etree.parse("data/characters.xml").getroot() player_t = tree.xpath(name)[0] player_class = player_t.find('class').text.strip() race = player_t.find('race').text.strip() lvl = player_t.find('lvl') if lvl is None: # If lvl is not informed, default value is assumes to be 1 lvl = 1 else: lvl = int(lvl.text.strip()) defense = int(player_t.find('initDef').text.strip()) res = int(player_t.find('initRes').text.strip()) hp = int(player_t.find('initHP').text.strip()) strength = int(player_t.find('initStrength').text.strip()) move = int(player_t.find('move').text.strip()) sprite = 'imgs/dungeon_crawl/player/' + player_t.find( 'sprite').text.strip() compl_sprite = player_t.find('complementSprite') if compl_sprite is not None: compl_sprite = 'imgs/dungeon_crawl/player/' + compl_sprite.text.strip( ) equipment = player_t.find('equipment') equipments = [] for eq in equipment.findall('*'): equipments.append(Level.parse_item_file(eq.text.strip())) gold = int(player_t.find('gold').text.strip()) # Creating player instance player = Player(name, sprite, hp, defense, res, move, strength, [player_class], equipments, race, gold, lvl, compl_sprite=compl_sprite) # Up stats according to current lvl player.stats_up(lvl - 1) # Restore hp due to lvl up player.healed() inventory = player_t.find('inventory') for it in inventory.findall('item'): item = Level.parse_item_file(it.text.strip()) player.set_item(item) return player @staticmethod def load_level(level, team): return Level('maps/level_' + level + '/', team) def new_game(self): # Init player's team (one character at beginning) team = [self.init_player("john"), self.init_player("archer")] # Init the first level level = StartScreen.load_level("0", team) self.play(level) def load_game(self): try: save = open("saves/main_save.xml", "r") # Test if there is a current saved game if save: tree_root = etree.parse("saves/main_save.xml").getroot() level_name = tree_root.find("level/name").text.strip() game_status = tree_root.find("level/phase").text.strip() turn_nb = 0 if game_status != 'I': turn_nb = int(tree_root.find("level/turn").text.strip()) team = [] for player in tree_root.findall("team/player"): name = player.find("name").text.strip() level = int(player.find("level").text.strip()) p_class = player.find("class").text.strip() race = player.find("race").text.strip() gold = int(player.find("gold").text.strip()) exp = int(player.find("exp").text.strip()) hp = int(player.find("hp").text.strip()) strength = int(player.find("strength").text.strip()) defense = int(player.find("defense").text.strip()) res = int(player.find("res").text.strip()) move = int(player.find("move").text.strip()) current_hp = int(player.find("currentHp").text.strip()) pos = (int(player.find("position/x").text.strip()), int(player.find("position/y").text.strip())) state = player.find("turnFinished").text.strip() inv = [] for it in player.findall("inventory/item"): it_name = it.find("name").text.strip() item = Level.parse_item_file(it_name) inv.append(item) equipments = [] for eq in player.findall("equipments/equipment"): eq_name = eq.find("name").text.strip() eq = Level.parse_item_file(eq_name) equipments.append(eq) # -- Reading of the XML file for default character's values (i.e. sprites) tree = etree.parse("data/characters.xml").getroot() player_t = tree.xpath(name)[0] sprite = 'imgs/dungeon_crawl/player/' + player_t.find( 'sprite').text.strip() compl_sprite = player_t.find('complementSprite') if compl_sprite is not None: compl_sprite = 'imgs/dungeon_crawl/player/' + compl_sprite.text.strip( ) p = Player(name, sprite, hp, defense, res, move, strength, [p_class], equipments, race, gold, level, compl_sprite=compl_sprite) p.earn_xp(exp) p.set_items(inv) p.set_current_hp(current_hp) p.set_pos(pos) if state == "True": p.turn_finished() team.append(p) # Load level with current game status, foes states, and team level = Level(level_name, team, game_status, turn_nb, tree_root.find("level/entities")) self.play(level) save.close() return except FileNotFoundError as err: pass # No saved game self.background_menus.append([self.active_menu, True]) name = "Load Game" entries = [[{ 'type': 'text', 'text': "No saved game.", 'font': ITEM_DESC_FONT }]] width = self.screen.get_width() // 2 self.active_menu = InfoBox(name, "", "imgs/interface/PopUpMenu.png", entries, width, close_button=1) def options_menu(self): self.background_menus.append([self.active_menu, False]) self.active_menu = StartScreen.create_options_menu() @staticmethod def exit_game(): pg.quit() raise SystemExit def main_menu_action(self, method_id, args): # Execute action if method_id == NEW_GAME_ACTION_ID: self.new_game() elif method_id == LOAD_GAME_ACTION_ID: self.load_game() elif method_id == OPTIONS_ACTION_ID: self.options_menu() elif method_id == EXIT_ACTION_ID: self.exit_game() else: print("Unknown action... : ", method_id) def options_menu_action(self, method_id, args): # Execute action if method_id == CHANGE_MOVE_SPEED: Movable.move_speed = args[2][0] StartScreen.modify_options_file("move_speed", args[2][0]) else: print("Unknown action... : ", method_id) def execute_action(self, menu_type, action): if not action: return method_id = action[0] args = action[1] # Test if the action is a generic one (according to the method_id) # Close menu : Active menu is closed if method_id == CLOSE_ACTION_ID: self.active_menu = None if self.background_menus: self.active_menu = self.background_menus.pop()[0] return if menu_type == START_MENU_ID: self.main_menu_action(method_id, args) elif menu_type == OPTIONS_MENU_ID: self.options_menu_action(method_id, args) else: print("Unknown menu... : ", menu_type) def motion(self, pos): if self.level is None: self.active_menu.motion(pos) else: self.level.motion(pos) def click(self, button, pos): if self.level is None: if button == 1: self.execute_action(self.active_menu.get_type(), self.active_menu.click(pos)) else: self.level.click(button, pos) def button_down(self, button, pos): if self.level is not None: self.level.button_down(button, pos)
def load_game(self): try: save = open("saves/main_save.xml", "r") # Test if there is a current saved game if save: tree_root = etree.parse("saves/main_save.xml").getroot() index = tree_root.find("level/index").text.strip() level_name = 'maps/level_' + index + '/' game_status = tree_root.find("level/phase").text.strip() turn_nb = 0 if game_status != 'I': turn_nb = int(tree_root.find("level/turn").text.strip()) team = [] for player in tree_root.findall("team/player"): name = player.find("name").text.strip() level = int(player.find("level").text.strip()) p_class = player.find("class").text.strip() race = player.find("race").text.strip() gold = int(player.find("gold").text.strip()) exp = int(player.find("exp").text.strip()) hp = int(player.find("hp").text.strip()) strength = int(player.find("strength").text.strip()) defense = int(player.find("defense").text.strip()) res = int(player.find("resistance").text.strip()) current_hp = int(player.find("currentHp").text.strip()) pos = (int(player.find("position/x").text.strip()) * TILE_SIZE, int(player.find("position/y").text.strip()) * TILE_SIZE) state = player.find("turnFinished").text.strip() inv = [] for it in player.findall("inventory/item"): it_name = it.find("name").text.strip() item = LoadFromXMLManager.parse_item_file(it_name) inv.append(item) equipments = [] for eq in player.findall("equipment/*"): eq_name = eq.text.strip() eq = LoadFromXMLManager.parse_item_file(eq_name) equipments.append(eq) skills = [ (LoadFromXMLManager.load_skill(skill.text.strip()) if skill.text.strip() not in LoadFromXMLManager.skills_infos else LoadFromXMLManager.skills_infos[skill.text.strip()]) for skill in player.findall('skills/skill/name') ] # -- Reading of the XML file for default character's values (i.e. sprites) tree = etree.parse("data/characters.xml").getroot() player_t = tree.xpath(name)[0] sprite = 'imgs/' + player_t.find('sprite').text.strip() compl_sprite = player_t.find('complementSprite') if compl_sprite is not None: compl_sprite = 'imgs/' + compl_sprite.text.strip() p = Player(name, sprite, hp, defense, res, strength, [p_class], equipments, race, gold, level, skills, compl_sprite=compl_sprite) p.earn_xp(exp) p.items = inv p.set_current_hp(current_hp) p.pos = pos if state == "True": p.turn_finished() team.append(p) # Load level with current game status, foes states, and team self.level_id = int(index) level = Level(level_name, team, self.level_id, game_status, turn_nb, tree_root.find("level/entities")) self.play(level) save.close() return except FileNotFoundError: # No saved game self.background_menus.append([self.active_menu, True]) name = "Load Game" entries = [[{ 'type': 'text', 'text': "No saved game.", 'font': fonts['MENU_SUB_TITLE_FONT'] }]] width = self.screen.get_width() // 2 self.active_menu = InfoBox(name, "", "imgs/interface/PopUpMenu.png", entries, width, close_button=1)