def cursor_in_menu_bounds(self): mouse_x = get_pos()[0] / SETTINGS.get(Setting.SCREEN_SCALE) mouse_y = get_pos()[1] / SETTINGS.get(Setting.SCREEN_SCALE) height = self.option_height * min(self.max_displayable_options, self.num_options) return self.root_x <= mouse_x <= self.root_x + self.width and self.root_y <= mouse_y <= self.root_y + height
def reset_menu(self): if self.current_menu[0] == Option.SETTINGS: SETTINGS.reset_settings() self.current_menu = generate_menu() self.menu_pos = 0 self.num_options = len(self.current_menu[1]) self.clamp_menu_bounds()
def convert_mouse_coords_to_cursor(self): mousex, mousey = pygame.mouse.get_pos() # Convert the screen coordinates to the grid coordinates self.gx = int( (mousex / SETTINGS.get(Setting.SCREEN_SCALE) + self.camera_x) // GRID_WIDTH) self.gy = int( (mousey / SETTINGS.get(Setting.SCREEN_SCALE) + self.camera_y) // GRID_HEIGHT)
def autosave(self): if SESSION.is_active(): timer = Timer(SETTINGS.get(Setting.AUTOSAVE_INTERVAL), self.autosave) timer.daemon = True timer.start() SESSION.save_game_to_file(autosave=True)
def generate_menu(): loadable_maps = convert_loadable_maps_to_options(AssetType.MAP) loadable_saves = convert_loadable_maps_to_options(AssetType.SAVE) local_option = (Option.LOCAL, [(Option.NEW_GAME, loadable_maps)]) if len(loadable_saves) > 0: local_option[1].append((Option.LOAD_GAME, loadable_saves)) host_option = (Option.HOST_GAME, [(Option.NEW_NETWORK_GAME, loadable_maps) ]) if len(loadable_saves) > 0: host_option[1].append((Option.LOAD_NETWORK_GAME, loadable_saves)) start_menu_options = [ (Option.CAMPAIGN, generate_campaign_menu()), local_option, ] if SETTINGS.get(Setting.NETWORK_ENABLED) == "True": start_menu_options.append( (Option.NETWORK, [host_option, (Option.JOIN_GAME, [])]), ) start_menu_options.extend([(Option.LEVEL_EDITOR, [(Option.NEW_MAP, []), (Option.LOAD_MAP, loadable_maps)]), (Option.SETTINGS, generate_settings_menu()), (Option.TUTORIAL, []), (Option.QUIT, [])]) return Option.START, start_menu_options
def __init__(self, piece_type=PieceType.COLONIST, team=Team.RED, gx=0, gy=0, hp=None): self.team = team self.gx = gx self.gy = gy # Rendered grid coordinates. Will line up with the grid coords over time for smoothish animation. self.rendered_gx = self.gx * GRID_WIDTH self.rendered_gy = self.gy * GRID_HEIGHT # How quickly pieces will animate and scroll to their correct locations. Higher number = slower movement self.move_animation_speed = 12 / ( NETWORK_ANIMATION_SPEED if self.is_network_game() else SETTINGS.get(Setting.ANIMATION_SPEED)) self.move_animation_snap_dist = 1 # Look up values based on our piece type self.piece_type = piece_type self.piece_subtype = self.attr(Attribute.SUBTYPE) self.piece_archetype = self.attr(Attribute.ARCHETYPE) # Interpreted variables. Don't touch! if hp: self.hp = hp else: self.hp = self.attr(Attribute.MAX_HP) self.current_order = None self.in_conflict = False self.temporary_armor = 0 self.last_attacker = None self.temporary_aoe_on_death = 0 self.temporary_money_lost_on_death = 0 self.previewing_order = False # AI pathfinding caching self.current_goal = None self.current_path = None indexed_pieces = [ PieceType.COLONIST, PieceType.TROOPER, PieceType.RANGER, PieceType.GHOST, PieceType.GUARDIAN, PieceType.BOLTCASTER, PieceType.BANSHEE, PieceType.TITAN, PieceType.EARTHRENDER, PieceType.DEMON ] framerate = 8 if team is not Team.NONE else 0 super().__init__(spr_pieces[self.team][self.piece_type], 24, framerate, indexed=self.piece_type in indexed_pieces, use_global_animation_frame=team is not Team.NONE, own_frames_for_index=True)
def __init__(self, map_name): super().__init__() Session.set_up_level_editor(map_name) # Begin scheduling autosaves if SETTINGS.get(Setting.AUTOSAVE_INTERVAL) > 0: self.autosave()
def handle_text_input(self, event): self.text_input.destroy() self.text_input = None if event.input: if event.tag == Option.NEW_MAP: publish_game_event(EventType.MENU_SELECT_OPTION, { 'option': event.tag, 'mapname': event.input + ".map" }) elif event.tag == Option.JOIN_GAME: publish_game_event(EventType.MENU_SELECT_OPTION, { 'option': event.tag, 'address': event.input }) elif event.tag == Setting.NICKNAME: SETTINGS.set_nonnumeric_setting(Setting.NICKNAME, event.input)
def __init__(self, map_name=None, map_type=None, create_session=True): super().__init__() # Only create the session if nothing else has (e.g. the network lobby) if create_session: Session.set_up_local_game(map_name, map_type) # Begin scheduling autosaves if SETTINGS.get(Setting.AUTOSAVE_INTERVAL) > 0: self.autosave()
def scroll_camera(self): map = self.get_manager(Manager.MAP) if self.is_active(): mousex, mousey = pygame.mouse.get_pos() # Convert the screen coordinates to the grid coordinates self.gx = int( clamp((mousex / SETTINGS.get(Setting.SCREEN_SCALE) + self.camera_x) // GRID_WIDTH, 0, map.width - 1)) self.gy = int( clamp((mousey / SETTINGS.get(Setting.SCREEN_SCALE) + self.camera_y) // GRID_HEIGHT, 0, map.height - 1)) camera_min_gx = self.camera_dest_x // GRID_WIDTH camera_min_gy = self.camera_dest_y // GRID_HEIGHT camera_max_gx = camera_min_gx + CAMERA_WIDTH // GRID_WIDTH camera_max_gy = camera_min_gy + CAMERA_HEIGHT // GRID_HEIGHT if self.gx >= camera_max_gx - camera_scroll_border: self.camera_dest_x += GRID_WIDTH if self.gx <= camera_min_gx + camera_scroll_border: self.camera_dest_x -= GRID_WIDTH if self.gy >= camera_max_gy - camera_scroll_border: self.camera_dest_y += GRID_HEIGHT if self.gy <= camera_min_gy + camera_scroll_border: self.camera_dest_y -= GRID_HEIGHT self.camera_dest_x = clamp(self.camera_dest_x, 0, map.width * GRID_WIDTH - CAMERA_WIDTH) self.camera_dest_y = clamp(self.camera_dest_y, 0, map.height * GRID_HEIGHT - CAMERA_HEIGHT) # Scroll the actual camera position to the destination coords if self.camera_x != self.camera_dest_x: self.camera_x += (self.camera_dest_x - self.camera_x) / camera_scroll_speed if abs(self.camera_x - self.camera_dest_x) <= camera_lock_distance: self.camera_x = self.camera_dest_x if self.camera_y != self.camera_dest_y: self.camera_y += (self.camera_dest_y - self.camera_y) / camera_scroll_speed if abs(self.camera_y - self.camera_dest_y) <= camera_lock_distance: self.camera_y = self.camera_dest_y
def __init__(self, bitmap=None, width=10, height=10): super().__init__() # Use a provided bitmap to generate tiles, otherwise generate one of the provided size # These are only integers (not tiles) for faster modification. if bitmap: self.bitmap = bitmap else: self.bitmap = generate_bitmap_from_simplex_noise(width, height) self.height = len(self.bitmap) self.width = len(self.bitmap[0]) # Serialize the map to Tile objects (from integers) self.tile_grid = self.convert_grid_from_bitmap(self.bitmap) # Adjust the grid opacity spr_grid.set_alpha(256 * SETTINGS.get(Setting.GRID_OPACITY) / 100)
def __init__(self, address, teams, is_host=True): super().__init__() if teams: self.open_teams = [Team[team.split(' ')[0]] for team in teams] else: self.open_teams = [] self.filled_teams = {} if not address: # Don't do any networking. self.networked_game = False self.team = self.get_next_open_team() else: self.networked_game = True self.is_host = is_host self.address = address self.server_port = SERVER_PORT self.nickname = SETTINGS.get(Setting.NICKNAME) self.connection = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.read_list = [self.connection] self.write_list = [] self.map_data = None if self.is_host: # Set ourselves up as the server / host self.connection.bind(("localhost", SERVER_PORT)) self.clients = [] # Automatically take the first team available self.team = self.get_next_open_team(self.nickname) else: # Set ourselves up as a client, connecting to the host self.client_port = random.randrange(7008, 7999) self.connection.bind(("localhost", self.client_port)) # We don't know our team or what map we're on yet! # Wait for a message to come back telling us who and where we are self.team = None self.connect_to_host()
def confirm(self): super().confirm() if 0 <= self.menu_pos < self.num_options: selection = self.current_menu[1][self.menu_pos] if not selection[0] in Setting: if len(selection[1]) > 0: self.current_menu = selection self.menu_pos = 0 self.num_options = len(selection[1]) self.clamp_menu_bounds() else: self.handle_menu_selection(selection) elif selection[0] == Setting.NICKNAME: self.text_input = TextInput("NICKNAME_INPUT", selection[0], default_text=SETTINGS.get_unsaved( Setting.NICKNAME), input_filter=FILTER_ALPHANUMERIC)
def __init__(self, meta): super().__init__() self.turn = 1 self.phase = BattlePhase.START_TURN self.timer = 0 # How long each phase's animation should take (in seconds) self.phase_animation_length = 1 / 4 self.framerate = NETWORK_ANIMATION_SPEED if self.is_network_game( ) else SETTINGS.get(Setting.ANIMATION_SPEED) # Initialize any data from metadata we care about for key, value in meta.items(): if key == MetadataKey.TURN.value: self.turn = int(value) elif key == MetadataKey.PHASE.value: self.phase = BattlePhase[value] publish_game_event(self.phase_events[self.phase], {"turn_number": self.turn}) if self.phase == BattlePhase.START_TURN: self.progress_phase(None)
def raise_setting(self): selection, _ = self.current_menu[1][self.menu_pos] if selection in numeric_settings: SETTINGS.raise_setting(selection)
def render(self, game_screen, ui_screen): super().render(game_screen, ui_screen) if self.text_input: self.text_input.render(game_screen, ui_screen) elif self.tutorial: self.tutorial.render(game_screen, ui_screen) else: # Draw text for the menu title menu_title_text = get_text(main_menu_strings, self.current_menu[0]) game_screen.blit( self.draw_menu_box(self.width - 16, 24, background=light_team_color[Team.RED]), (self.root_x - 8, self.root_y - 16)) game_screen.blit(menu_title_text, (self.root_x + 24, self.root_y - 12)) # Draw a scrollbar if necessary if self.should_show_scroll_bar(self.max_displayable_options, self.num_options): width = 8 height = self.option_height * min(self.max_displayable_options, self.num_options) game_screen.blit( self.draw_scroll_bar(width, height, self.max_displayable_options, self.menu_min, self.num_options), (self.root_x + self.width - 24, self.root_y)) # Draw each menu option row_y = 0 displayable_options = self.current_menu[1][self.menu_min:self. menu_max] for option in displayable_options: is_selected = self.menu_pos == self.current_menu[1].index( option) x_offset = 0 if is_selected else 16 position_x, position_y = self.root_x, self.root_y + row_y * self.option_height box = self.draw_menu_box( self.width - x_offset, self.option_height, background=light_team_color[Team.RED] if is_selected else shadow_color[Team.RED]) game_screen.blit(box, (position_x - 24 + x_offset, position_y)) # Render splash graphics for top-level menu options if is_selected and self.current_menu[0] == Option.START: splash_width = self.width - 24 splash_height = 24 * (self.max_displayable_options) game_screen.blit( self.draw_menu_box(splash_width, splash_height), (self.root_x - splash_width - 24, self.root_y)) game_screen.blit( spr_main_menu_preview[option[0]], (self.root_x - splash_width - 12, self.root_y + 12)) game_screen.fill(clear_color[Team.RED], (self.root_x - splash_width - 12, self.root_y + 132, 120, 2)) if isinstance(option[0], str): # Render arbitrary text # Format the text a bit text = option[0]\ .replace("_", " ")\ .replace(".map", "")\ .replace(".sav", "")\ .title() # Render arbitrary text game_screen.blit(draw_text(text, light_color, dark_color), (position_x + 8, position_y + 8)) # For campaign, render an icon for completed missions if option[0] in self.progress: game_screen.blit( spr_mission_completed, (position_x + self.width - 48, position_y - 2)) # Render map previews if we're trying to select a map if is_selected and self.current_menu[0] in [ Option.NEW_GAME, Option.NEW_MAP, Option.LOAD_GAME, Option.LOAD_MAP, Option.NEW_NETWORK_GAME, Option.LOAD_NETWORK_GAME, Option.NEW_CAMPAIGN_GAME, Option.LOAD_CAMPAIGN_GAME ]: if self.current_menu[0] in [ Option.LOAD_GAME, Option.LOAD_NETWORK_GAME ]: asset_type = AssetType.SAVE elif self.current_menu[0] in [ Option.NEW_CAMPAIGN_GAME ]: asset_type = AssetType.CAMPAIGN_MAP elif self.current_menu[0] in [ Option.LOAD_CAMPAIGN_GAME ]: asset_type = AssetType.CAMPAIGN_SAVE else: asset_type = AssetType.MAP container_height = 24 * self.max_displayable_options container_width = self.width - 24 map_preview = draw_map_preview_from_file( container_width, container_height, option[0], asset_type=asset_type) game_screen.blit( map_preview, (self.root_x - container_width - 24, self.root_y)) elif option[0] in Setting: # Display the setting prompt and the current value display_string = get_string( formatted_strings, option[0]).format(SETTINGS.get_unsaved(option[0])) game_screen.blit( draw_text(display_string, light_color, dark_color), (position_x + 24, position_y + 8)) else: # Display the icon for the option game_screen.blit(spr_main_menu_option[option[0]], (position_x - 24 + x_offset, position_y)) # Display prerendered text game_screen.blit(get_text(main_menu_strings, option[0]), (position_x + 24, position_y + 8)) row_y += 1
def play_sound(self, sound_type): sound = sound_type.value sound.set_volume(SETTINGS.get(Setting.SFX_VOLUME) / 100) sound.stop() sound.play()
def load_sound(resource_name): sound = pygame.mixer.Sound(get_asset(AssetType.SOUND, resource_name)) sound.set_volume(SETTINGS.get(Setting.SFX_VOLUME) / 100) all_sounds.append(sound) return sound
def set_cursor_pos_to_mouse_coords(self): if self.cursor_in_menu_bounds(): self.menu_pos = clamp( (int(get_pos()[1] / SETTINGS.get(Setting.SCREEN_SCALE)) - self.root_y) // 24 + self.menu_min, self.menu_min, self.menu_max)