def __init__(self, model, view): self.model = model self.view = view # Add Background layer to visible models self.view.add_model(None, InventoryView.render_background, Position(0, 0), View.BACKGROUND) # Add Character to visible models self.view.add_model(self.model.character, InventoryView.render_character_data, Position(Map.MAP_SIZE / 4, 0), View.FOREGROUND) # Add item description - using blank item for initialization self.description_item = Item(0, 0, "", 0) self.view.add_model(self.description_item, InventoryView.render_description, Position(0, 0), View.FOREGROUND) # Build item list from model into a menu self.inventory_menu = Menu(self.view, InventoryView.render_inventory_menu, self.on_node_activated, Position(0, 0)) for item in self.model.character.inventory.item_list: self.inventory_menu.nodes.append( LeafNode(item.name, self.select_item, item))
def on_node_activated(self, node): if node.is_leaf_node(): result = node.execute_action() # Add save game nodes to menu it consists of allowing the user to overwrite any # existing save or add a new one. if node.id == self.save_game_node_id: game_menu = Menu( self.view, MainMenu.render_menu, self.on_node_activated, Position(Map.MAP_SIZE / 2 - MainMenu.MENU_WIDTH / 2, Map.MAP_SIZE / 2 - MainMenu.MENU_HEIGHT / 2)) self.save_node_ids = utils.add_saved_game_nodes( game_menu, Database().save_game_overwrite, self.game_model.create_memento()) new_node = LeafNode("New Saved Game", Database().save_game, self.game_model.create_memento()) game_menu.nodes.append(new_node) self.save_node_ids.append(new_node.id) node.submenu = game_menu # Add load game nodes to menu it allows a user to load any existing save. if node.id == self.load_game_node_id: game_menu = Menu( self.view, MainMenu.render_menu, self.on_node_activated, Position(Map.MAP_SIZE / 2 - MainMenu.MENU_WIDTH / 2, Map.MAP_SIZE / 2 - MainMenu.MENU_HEIGHT / 2)) self.load_node_ids = utils.add_saved_game_nodes( game_menu, Database().load_saved_game, None) node.submenu = game_menu # If user has selected a save node if node.id in self.save_node_ids: utils.return_to_game(self.game_model) # If user has selected a load node if node.id in self.load_node_ids: self.game_model.set_memento(result) utils.return_to_game(self.game_model)
def __init__(self, name, image, health, attack, defense): self.name = name self.image = image self.health = health self.total_health = health self.attack = attack self.defense = defense self.position = Position(1, 1) self.direction = Character.DOWN self.inventory = Inventory({}) self.loadout = {}
def _change_map(self, map_name): self.changed_map = True self.view.remove_model(self.model.current_map) prev_music = self.model.current_map.music self.model.current_map = self.model.maps[map_name] # Change the music if necessary curr_music = self.model.current_map.music if prev_music != curr_music: pygame.mixer.music.load( os.path.join('Music', self.model.current_map.music)) pygame.mixer.music.play() self.view.add_model(self.model.current_map, GameView.render_map, Position(0, 0), View.BACKGROUND) self.triggers = {} self.previous_position = None self._build_triggers()
def render_map(map, screen, *args, **kwargs): #render layer 1 for x in range(0, map.grid_size): for y in range(0, map.grid_size): position = Position(x, y) if map.layers[0][x][y] != 0: screen.blit(map.layers[0][x][y].image, position.convert_to_pixels(0)) #render layer 2 for x in range(0, map.grid_size): for y in range(0, map.grid_size): position = Position(x, y) if map.layers[1][x][y] != 0: screen.blit(map.layers[1][x][y].image, position.convert_to_pixels(0))
def __init__(self, model, view, enemy_name): self.model = model self.view = view self.state = BattleController.ACTION_SELECT self.current_action = None self.enemy = copy.copy(model.enemies[enemy_name]) # Add Character model self.view.add_model(self.model.character, BattleView.render_character, Position(Map.GRID_SIZE / 2, Map.GRID_SIZE / 2), View.FOREGROUND) # Add Map Model self.view.add_model( self.model.current_map.get_map_tile( self.model.character.position.x_coord, self.model.character.position.y_coord, 0), BattleView.render_map, Position(0, Map.MAP_SIZE - BattleView.MENU_HEIGHT), View.BACKGROUND) # Add Enemy self.view.add_model(self.enemy, BattleView.render_enemy, Position(Map.GRID_SIZE / 2, 2), View.FOREGROUND) # Add target window Model and set current target to player characters = {'Player': self.model.character, 'Enemy': self.enemy} self.target_window = TargetWindow(self.model.character, self.state, characters) self.view.add_model(self.target_window, BattleView.render_target_window, Position(Map.GRID_SIZE / 2, Map.GRID_SIZE / 2), View.FOREGROUND) # Add action select menu to visible models self.action_menu = Menu( self.view, BattleView.render_menu, self.on_node_activated, Position(0, Map.MAP_SIZE - BattleView.MENU_HEIGHT)) self.action_menu.nodes.append( LeafNode("Attack", self.set_attack_action)) self.action_menu.nodes.append(LeafNode("Items", None)) # Add Battle Log self.battle_log = BattleLog("%s Attacked!" % enemy_name) self.view.add_model(self.battle_log, BattleView.render_battle_log, Position(0, 0), View.FOREGROUND)
def __init__(self, model, view): self.game_model = model self.view = view self.save_node_ids = [] self.load_node_ids = [] pygame.mixer.music.load(os.path.join('Music', 'theme.mid')) pygame.mixer.music.play() self.menu_model = Menu(self.view, TitleScreenView.render_menu, self.on_node_activated, Position(0, 0)) new_game_node = LeafNode("New Game", utils.return_to_game, self.game_model) self.menu_model.nodes.append(new_game_node) self.new_game_node_id = new_game_node.id load_game_node = MenuNode("Load Saved Game") self.menu_model.nodes.append(load_game_node) self.load_game_node_id = load_game_node.id self.menu_model.nodes.append(LeafNode("Quit", utils.quit))
def __init__(self, model, view, previous_controller, previous_view): self.game_model = model self.view = view self.previous_controller = previous_controller self.previous_view = previous_view self.save_node_ids = [] self.load_node_ids = [] self.menu_model = Menu( self.view, MainMenu.render_menu, self.on_node_activated, Position(Map.MAP_SIZE / 2 - MainMenu.MENU_WIDTH / 2, Map.MAP_SIZE / 2 - MainMenu.MENU_HEIGHT / 2)) save_game_node = MenuNode("Save Game") self.menu_model.nodes.append(save_game_node) self.save_game_node_id = save_game_node.id load_game_node = MenuNode("Load Saved Game") self.menu_model.nodes.append(load_game_node) self.load_game_node_id = load_game_node.id self.menu_model.nodes.append(LeafNode("Quit", utils.quit))
def __init__(self, model, view): self.model = model self.view = view self.triggers = {} self.previous_position = None self.changed_map = False self.unmoved = True pygame.mixer.music.load( os.path.join('Music', self.model.current_map.music)) pygame.mixer.music.play() self._build_triggers() # Add Map model view.add_model(model.current_map, GameView.render_map, Position(0, 0), View.BACKGROUND) # Add Character model view.add_model(model.character, GameView.render_character, model.character.position, GameView.FOREGROUND) self.unmoved = True
def load_saved_game(self, memento_id, *args, **kwargs): cursor = self._database_execute( "SELECT Current_Map, Character_Position_X, Character_Position_Y, Character_Health, " "Character_Total_Health, Character_Attack, Character_Defense FROM GameState WHERE Id = %s" % memento_id, None) memento_row = cursor.fetchone() current_map = memento_row['Current_Map'] character_position = Position( memento_row['Character_Position_X'], memento_row['Character_Position_Y']) cursor = self._database_execute( "SELECT * FROM InventoryState JOIN Item on InventoryState.Item_ID = Item.Id " "WHERE InventoryState.Game_State_Id = '%s'" % memento_id, None ) items = cursor.fetchall() item_dict = {} loadout = {} types = self.create_types_dict() for item in items: item_init = types[item['Type']] new_item = item_init(item['Id'], item['Name'], item['Description'], item['Slot'], item['Modifier']) if item['Equipped'] == 1: loadout[item['Slot']] = new_item item_dict[new_item] = item['Quantity'] character_memento = CharacterMemento(character_position, memento_row['Character_Health'], memento_row['Character_Total_Health'], memento_row['Character_Attack'], memento_row['Character_Defense'], item_dict, loadout) game_memento = GameMemento(current_map, character_memento) return game_memento
def on_node_activated(self, node): if node.is_leaf_node(): result = node.execute_action() # Add load game nodes to menu it allows a user to load any existing save. if node.id == self.load_game_node_id: game_menu = Menu(self.view, TitleScreenView.render_menu, self.on_node_activated, Position(0, 0)) self.load_node_ids = utils.add_saved_game_nodes( game_menu, Database().load_saved_game, None) node.submenu = game_menu # If user has selected new game if node.id == self.new_game_node_id: utils.return_to_game(self.game_model) # If user has selected a load node if node.id in self.load_node_ids: self.game_model.set_memento(result) utils.return_to_game(self.game_model)
def _load_maps(self): maps = {} # Game is now made up of multiple maps cursor = self._database_execute( "SELECT * FROM Map", None) loaded_maps = cursor.fetchall() for each_map in loaded_maps: game_map = Map(Map.GRID_SIZE, each_map["Name"], each_map["Music"]) # Load the map layers of this map cursor = self._database_execute( """SELECT ID, Layer FROM MapLayer WHERE MapId = %s""" % each_map['Id'], None) load_layers = cursor.fetchall() for each_layer in load_layers: # Load the map tiles for this map. cursor = self._database_execute( """SELECT mt.TileId, mt.Index_X, mt.Index_Y, t.Name, t.Walkable, t.Image, mt.Id FROM MapTile AS mt JOIN Tile as t ON mt.TileId = t.Id WHERE MapLayerId = %d""" % each_layer['Id'], None) map_tiles = cursor.fetchall() # Add all the tiles into the map. for row_map_tiles in map_tiles: tile_image = pygame.image.load( os.path.join('Images', row_map_tiles['Image'])) tile_image_scaled = pygame.transform.scale( tile_image, (Tile.SIZE, Tile.SIZE)) map_tile_id = row_map_tiles['Id'] # Add trigger for this tile. cursor = self._database_execute( """SELECT Chance, Action_Type, Triggered_On, Direction_Facing, One_Time, Action_Data FROM Trigger WHERE MapTileId = %s""" % map_tile_id, None) trigger_row = cursor.fetchone() if trigger_row is not None: trigger = Trigger( trigger_row['Chance'], trigger_row['Action_Type'], trigger_row['Triggered_On'], trigger_row['Direction_Facing'], trigger_row['One_Time'], trigger_row['Action_Data']) else: trigger = None position = Position( row_map_tiles['Index_X'], row_map_tiles['Index_Y']) tile = Tile( row_map_tiles['Name'], tile_image_scaled, position, trigger, row_map_tiles['Walkable']) if (each_layer["Layer"] == "Layer1"): game_map.add_or_replace_tile(0, tile) else: game_map.add_or_replace_tile(1, tile) maps[each_map['Name']] = game_map return maps
def _handle_trigger(self, trigger, position, is_previous, pressed_key): # We support triggers being fired when entering or leaving a tile. valid_previous_trigger = trigger.triggered_on == Trigger.EXIT and is_previous valid_current_trigger = trigger.triggered_on == Trigger.ENTER and not is_previous valid_action_trigger = trigger.triggered_on == Trigger.KEY_ACTION and \ pressed_key == pygame.K_e if not (valid_previous_trigger or valid_current_trigger or valid_action_trigger): return # Make sure the character is facing the appropriate direction if not (self.model.character.direction == trigger.direction_facing or \ trigger.direction_facing == Trigger.DIRECTION_ANY): return if trigger.is_one_time: trigger.is_active = False if trigger.action_type == Trigger.CHANGE_MAP: self._change_map(trigger.action_data['map_name']) position = Position(trigger.action_data['character_x'], trigger.action_data['character_y']) self.view.set_visible_model_position(self.model.character, position) if trigger.action_type == Trigger.START_BATTLE: self._start_battle(trigger.action_data['enemy'], position) if trigger.action_type == Trigger.GET_ITEM: self.model.character.inventory.\ add_item(self.model.items[trigger.action_data['item']]) # Use a dialog here to show that an item is acquired if trigger.action_type == Trigger.SHOW_DIALOG: if not self.unmoved: self.unmoved = True new_dialog = Dialog( Position(trigger.action_data['dialog_x'], trigger.action_data['dialog_y']), trigger.action_data['dialog_text'], trigger.action_data['timed'], trigger.action_data['timeout'], self) self.view.add_model(new_dialog, GameView.render_dialog, new_dialog.location, GameView.OVERLAY) if not new_dialog.timed: # TODO: Render icon to indicate manual procession base = utils.fetch( utils.qualify_controller_name("dialog_controller")) controller = base.DialogController(new_dialog, self.view) pygame.event.post( pygame.event.Event(event_types.UPDATE_GAME_STATE, { "Controller": controller, "View": self.view })) print("Action occurred with data: " + str(trigger.action_data))
def render_target_window(target_window, screen, position, *args, **kwargs): font = pygame.font.SysFont("monospace", BattleView.FONT_SIZE) base = utils.fetch(utils.qualify_controller_name( "battle_controller")) if target_window.battle_state is base.BattleController.TARGET_SELECT: # Render the target icon over the new target target_image = pygame.image.load( os.path.join('Images', "target_icon.png")) target_image_scaled = pygame.transform.scale( target_image, (10, 10)) screen.blit(target_image_scaled, position.convert_to_pixels(BattleView.TARGET_ICON_OFFSET)) # Render enemy stats window enemy_background = pygame.Surface((170, 110)) enemy_background.fill((5, 4, 71, 100)) enemy_stats_position = Position(11, 2) screen.blit(enemy_background, enemy_stats_position.convert_to_pixels(0)) enemy_name_label = font.render("%s" % target_window.characters['Enemy'].name, 1, (255, 255, 0)) enemy_health_label = font.render("HP: %d/%d" % (target_window.characters['Enemy'].health, target_window.characters['Enemy'].total_health), 1, (255, 255, 255)) enemy_attack_label = font.render("ATK: %d" % target_window.characters['Enemy'].attack, 1, (255, 255, 255)) enemy_defense_label = font.render("DEF: %d" % target_window.characters['Enemy'].defense, 1, (255, 255, 255)) screen.blit(enemy_name_label, enemy_stats_position.convert_with_offset(BattleView.PADDING, BattleView.PADDING)) screen.blit(enemy_health_label, enemy_stats_position.convert_with_offset(BattleView.PADDING, BattleView.LINE_HEIGHT + BattleView.PADDING)) screen.blit(enemy_attack_label, enemy_stats_position.convert_with_offset(BattleView.PADDING, 2 * BattleView.LINE_HEIGHT + BattleView.PADDING)) screen.blit(enemy_defense_label, enemy_stats_position.convert_with_offset(BattleView.PADDING, 3 * BattleView.LINE_HEIGHT + BattleView.PADDING)) # Render player stats window player_background = pygame.Surface((170, 110)) player_background.fill((5, 4, 71, 100)) player_stats_position = Position(2, 8) screen.blit(player_background, player_stats_position.convert_to_pixels(0)) player_name_label = font.render("%s" % target_window.characters['Player'].name, 1, (255, 255, 0)) player_health_label = font.render("HP: %d/%d" % (target_window.characters['Player'].health, target_window.characters['Player'].total_health) , 1, (255, 255, 255)) player_attack_label = font.render("ATK: %d" % target_window.characters['Player'].attack, 1, (255, 255, 255)) player_defense_label = font.render("DEF: %d" % target_window.characters['Player'].defense, 1, (255, 255, 255)) screen.blit(player_name_label, player_stats_position.convert_with_offset(BattleView.PADDING, BattleView.PADDING)) screen.blit(player_health_label, player_stats_position.convert_with_offset(BattleView.PADDING, BattleView.LINE_HEIGHT + BattleView.PADDING)) screen.blit(player_attack_label, player_stats_position.convert_with_offset(BattleView.PADDING, 2 * BattleView.LINE_HEIGHT + BattleView.PADDING)) screen.blit(player_defense_label, player_stats_position.convert_with_offset(BattleView.PADDING, 3 * BattleView.LINE_HEIGHT + BattleView.PADDING))
def render_map(game_tile, screen, *args, **kwargs): for x in range(0, Map.GRID_SIZE): for y in range(0, Map.GRID_SIZE): position = Position(x, y) screen.blit(game_tile.image, position.convert_to_pixels(0))