def show_splash_screen(self): """ Show the splash screen followed by and unending loop of the main menu. :return: """ Audio.start_music() GuiUtilities.show_splash(self.surface_display) while True: self.show_main_menu()
def event_window_resize(self, display_size): """ Event handler for window resize event. This function will reinitialize the pygame display and create properly sized surfaces for the interface. :param display_size: (width, height) :return: None """ if self.parent is None: GuiUtilities.set_display_size(display_size) else: self.parent.event_window_resize(display_size)
def show_effects(self): for effect in self.game.current_level.active_effects: # Current implementation looks at effect targetType to decide on a visualization option. if effect.targetType == TARGET.SELF: # flash tile on which actor is standing self.animation_flash_tiles(GuiUtilities.get_element_color(effect.effectElement), effect.tiles) elif effect.targetType == TARGET.ACTOR: # circle around the target character self.animation_nova(GuiUtilities.get_element_color(effect.effectElement), effect.actors[0].tile, effect.effectRadius) elif effect.targetType == TARGET.TILE: # circular blast around centerTile self.animation_nova(GuiUtilities.get_element_color(effect.effectElement), effect.centerTile, effect.effectRadius) else: print('WARNING: Unknown visualization type, skipping.')
def show_game_menu(self): options = ['Controls', 'Quit Game'] keys = ['c', 'q'] selection = GuiUtilities.show_menu(self.surface_display, 'Game Menu', options, keys) if selection is None: return elif selection == 0: print('Game Menu: ' + options[0]) GuiUtilities.show_message_controls(self.surface_display) elif selection == 1: print('Game Menu: ' + options[1]) self.stop_game() else: print('Game Menu: unknown selection...?')
def __init__(self, parent): """ Constructor After construction the interface the run() method should be called. :param parent: Parent interface on top of which this will be displayed. """ self._parent = parent self._surface_background = None self._run = False self.clock = None self._frame_rate = 0 self._frame_elapsed_time = 0 # Initialize pygame GuiUtilities.init_pygame()
def _initialize(self): super(MainMenuInterface, self)._initialize() Audio.start_music() # Splash screen if INTERFACE.SHOW_SPLASH_SCREEN: GuiUtilities.show_splash(self.surface_display) # Version Number self.surface_version = GuiUtilities.FONT_PANEL.render(self.version_number, 1, COLORS.PANEL_FONT) self.version_position = (10, self.surface_display.get_height() - self.surface_version.get_height() - 10) # Menu self.options = ['New game', 'Controls', 'Quit'] self.keys = ['n', 'c', 'q'] self.handlers = [self.event_new_game, self.event_show_controls, self.event_quit]
def event_targeting_acquire(self): # targeted tile is currently selected target_tile = self._renderSelectedTile # hack to avoid lingering selection tile self._renderSelectedTile = None # find target based on targetType if self._targetType == TARGET.TILE: my_target = target_tile elif self._targetType == TARGET.ACTOR: # Currently this finds all ACTORS, not limited to CHARACTERS # find target actor on tile if len(target_tile.actors) == 0: return if len(target_tile.actors) == 1: my_target = target_tile.actors[0] else: # show menu with options to target header = 'Select target (escape to cancel)' options = [] for a in target_tile.actors: options.append(a.name + ' (' + str(a.currentHitPoints) + '/' + str(a.maxHitPoints) + ')') selection = GuiUtilities.show_menu(self.surface_display, header, options) if selection is None: return else: my_target = target_tile.actors[selection] # use target item on target self.game.player.try_use_item(self._targetingItem, my_target) # Leave targeting mode self.event_targeting_stop()
def zoom_factor(self, factor): """ Set the zoom factor. A higher zoom factor results in bigger tile sizes in the viewport. :param factor: Float zoom factor :return: None """ self._zoom_factor = max(min(INTERFACE.MAX_ZOOM_FACTOR, factor), INTERFACE.MIN_ZOOM_FACTOR) # Calculate new tile size default_tile_size = 50 self.tile_size = int(default_tile_size * self.zoom_factor) # Initialize render font, a size of roughly 1,5 times the tileSize gives good results self._viewPortFont = GuiUtilities.viewport_font(self.tile_size) # Determine max coordinates for view port location total_width = self.player.level.map.width * self.tile_size total_height = self.player.level.map.height * self.tile_size self._renderViewPortMaxX = total_width - self.surface_viewport.get_width( ) self._renderViewPortMaxY = total_height - self.surface_viewport.get_height( ) if self._renderViewPortMaxX < 0: self._renderViewPortMaxX = 0 if self._renderViewPortMaxY < 0: self._renderViewPortMaxY = 0 # Prepare fog of war tile (used as overlay later) self.fogOfWarTileSurface = pygame.Surface( (self.tile_size, self.tile_size), pygame.SRCALPHA) self.fogOfWarTileSurface.fill((0, 0, 0, 140)) # Re-initialize sprites initialize_sprites(self.tile_size)
def _update_screen(self): self.surface_display.blit(self.surface_version, self.version_position) self.selection = GuiUtilities.show_menu(self.surface_display, 'Main Menu', self.options, self.keys) if self.selection is None: return else: print('Main Menu: ' + self.options[self.selection]) self.handlers[self.selection]()
def _handle_event(self, event): """ Main event handler, this is called once for every pending event during the main run loop. :param event: Pygame event :return: None """ # Pygame quit event if event.type == pygame.QUIT: sys.exit() # Window resize event elif event.type == VIDEORESIZE: self.event_window_resize(event.dict['size']) # keyboard events elif event.type == pygame.KEYDOWN: # Toggle fullscreen mode if event.unicode == 'f': GuiUtilities.toggle_fullscreen() self.event_window_resize(GuiUtilities.CURRENT_RESOLUTION)
def drop_inventory(self): """ Present inventory to player with possibility to drop an item. """ if self.game is not None and self.game.player is not None: header = "Select item to drop, escape to cancel" options = [] items = self.game.player.inventory.items for item in items: options.append(item.name) selection = GuiUtilities.show_menu(self.surface_display, header, options) if selection is not None: self.game.player.tryDropItem(items[selection])
def show_main_menu(self): options = ['New local game', 'Controls', 'Quit', 'Debug Maps', 'Connect to server'] keys = ['n', 'c', 'q', 'd', 's'] selection = GuiUtilities.show_menu(self.surface_display, 'Main Menu', options, keys) if selection is None: return elif selection == 0: print('Main Menu: ' + options[0]) self.new_game() elif selection == 1: print('Main Menu: ' + options[1]) GuiUtilities.show_message_controls(self.surface_display) elif selection == 2: print('Main Menu: ' + options[2]) sys.exit() elif selection == 3: print('Main Menu: ' + options[3]) self.debug_maps() elif selection == 4: print('Main Menu: ' + options[4]) self.connect_to_server() else: print('Main menu: unknown selection...?')
def use_inventory(self): """ Present inventory to player with possibility to use an item. """ if self.game is not None and self.game.player is not None: header = "Select item to use, escape to cancel" options = [] items = self.game.player.inventory.items for item in items: options.append(item.name) selection = GuiUtilities.show_menu(self.surface_display, header, options) if selection is not None: use_item = items[selection] if use_item.targeted: # ask player for target self.event_targeting_start(use_item) else: # try to use the item self.game.player.try_use_item(use_item)
def __init__(self): """ Constructor """ # Initialize PyGame pygame.mixer.pre_init(44100, -16, 2, 512) pygame.init() # Initialize fonts GuiUtilities.DEPRECATED_init_fonts() # Initialize audio Audio.init_audio() # Initialize properties self.render_level = None self._draggingMode = False self._targetingMode = False self._game_server = None # Initialize rendering variables self._renderSelectedTile = None self._zoomFactor = 1 self._renderViewPortX = 0 self._renderViewPortY = 0 # Initialize display surface display_info = pygame.display.Info() # Hack for my fullscreen # - I have two screens so divide width by two # - I have a window manager panel which always takes up 24 pixels on first screen self.fullscreen_sdl_position = "0, 0" self.fullscreen_size = (int(display_info.current_w // 2), display_info.current_h - 24) self.window_size = (1000, 750) self._fullscreen = False self.setup_surfaces(self.window_size) # Set mouse cursor pygame.mouse.set_cursor(*pygame.cursors.tri_left) # Initialize window title pygame.display.set_caption(INTERFACE.APPLICATION_NAME)
def render_init(self): """ Initializes rendering parameters Prepares and scales tileset. This function should be called on window resizing, loading a new level and changing zoom levels. """ if self.game_server is None: return # Initialize maximum tile size for current viewport vp_width = self.surface_viewport.get_size()[0] vp_height = self.surface_viewport.get_size()[1] max_tile_width = int(vp_width // self.render_level.map["width"]) max_tile_height = int(vp_height // self.render_level.map["height"]) if max_tile_width < max_tile_height: max_tile_size = max_tile_width else: max_tile_size = max_tile_height # Take into account the zoom factor self._tileSize = int(max_tile_size * self.zoom_factor) # Initialize render font, a size of roughly 1,5 times the tileSize gives good results self._viewPortFont = GuiUtilities.viewport_font(self.tile_size) # Determine max coords for view port location total_width = self.render_level.map["width"] * self.tile_size total_height = self.render_level.map["height"] * self.tile_size self._renderViewPortMaxX = total_width - self._render_viewport_w self._renderViewPortMaxY = total_height - self._render_viewport_h if self._renderViewPortMaxX < 0: self._renderViewPortMaxX = 0 if self._renderViewPortMaxY < 0: self._renderViewPortMaxY = 0 # Prepare fog of war tile (used as overlay later) self.fogOfWarTileSurface = pygame.Surface((self.tile_size, self.tile_size), pygame.SRCALPHA) self.fogOfWarTileSurface.fill((0, 0, 0, 140)) # Re-initialize sprites initialize_sprites(self.tile_size)
def render_panel(self): """ Update the content of the Panel surface """ # Erase panel self.surface_panel.fill(COLORS.PANEL_BG) # Left side (1/3) is used for player information, right side (2/3) is used for game messages width_offset = int(self.surface_panel.get_width() // 3) height_offset = self.surface_panel.get_height() # Left side: render player information available_width = width_offset x_offset = int(available_width // 10) y_offset = 0 spacer = 5 if self.game_server.player is not None: # Player name player_name = self.game_server.player.name + " (Lvl " + str(self.game_server.player.playerLevel) + ")" blit_text = GuiUtilities.FONT_PANEL.render(player_name, 1, COLORS.PANEL_FONT) self.surface_panel.blit(blit_text, (int(x_offset / 2), 2)) y_offset += spacer # Determine bar width & height bar_width = available_width - 2 * x_offset bar_height = GuiUtilities.FONT_PANEL.size("HP")[1] # Health bar y_offset += bar_height current_hp = self.game_server.player.currentHitPoints maximum_hp = self.game_server.player.maxHitPoints pygame.draw.rect(self.surface_panel, COLORS.BAR_HEALTH_BG, (x_offset, y_offset, bar_width, bar_height)) if current_hp > 0: fil_width = int((current_hp * bar_width) // maximum_hp) pygame.draw.rect(self.surface_panel, COLORS.BAR_HEALTH, (x_offset, y_offset, fil_width, bar_height)) text = "HP: " + str(current_hp) + "/" + str(maximum_hp) blit_text = GuiUtilities.FONT_PANEL.render(text, 1, COLORS.PANEL_FONT) self.surface_panel.blit(blit_text, (x_offset, y_offset)) y_offset += bar_height + spacer # XP bar current_hp = self.game_server.player.xp maximum_hp = self.game_server.player.nextLevelXp pygame.draw.rect(self.surface_panel, COLORS.BAR_XP_BG, (x_offset, y_offset, bar_width, bar_height)) if current_hp > 0: fil_width = int((current_hp*bar_width) // maximum_hp) pygame.draw.rect(self.surface_panel, COLORS.BAR_XP, (x_offset, y_offset, fil_width, bar_height)) text = "XP: " + str(current_hp) + "/" + str(maximum_hp) blit_text = GuiUtilities.FONT_PANEL.render(text, 1, COLORS.PANEL_FONT) self.surface_panel.blit(blit_text, (x_offset, y_offset)) # Right side: render game messages message_counter = 1 nbr_of_messages = len(self.game_server.messageBuffer) while height_offset > 0: if message_counter > nbr_of_messages: break # Get messages from game message buffer, starting from the back message = self.game_server.messageBuffer[nbr_of_messages - message_counter] # Create text lines for message text_lines = GuiUtilities.wrap_multi_line(message, GuiUtilities.FONT_PANEL, self.surface_panel.get_width() - width_offset) nbr_of_lines = len(text_lines) # Blit the lines for l in range(1, nbr_of_lines+1): blit_line = GuiUtilities.FONT_PANEL.render(text_lines[nbr_of_lines - l], 1, COLORS.PANEL_FONT) height_offset = height_offset - blit_line.get_height() # Only blit the line if there is enough remaining space to show it completely if height_offset > blit_line.get_height(): self.surface_panel.blit(blit_line, (width_offset, height_offset)) message_counter += 1
def event_show_controls(self): """ Event handler to show game controls. :return: None """ GuiUtilities.show_message_controls(self.surface_display)