def _init_text_box(self, x_pos, y_pos, w, h, text, color, color_text): box_size = (w, h) user_box = RectLabel(x_pos, y_pos, box_size[0], box_size[1], color, 0, Text(pygame.font.SysFont('Agency FB', 25), text, color_text)) user_box.change_bg_image(WOOD) user_box.add_frame(FRAME) self.sprite_grp.add(user_box)
def _init_log_box(self, clr): box_size = (self.resolution[0] / 2, self.resolution[1] / 2) x_pos = self.resolution[0] / 2 - box_size[0] / 2 y_pos = self.resolution[1] / 2 - box_size[1] / 2 log_box = RectLabel(x_pos, y_pos, box_size[0], box_size[1], clr) log_box.change_bg_image(WOOD) log_box.add_frame(FRAME) self.sprite_grp.add(log_box)
def _init_load_menu(self, x_pos: int, y_pos: int, text: str, color: color, color_text: color): user_box = RectLabel( x_pos, y_pos, 500, 500, color, 0, Text(pygame.font.SysFont('Agency FB', 25), text, color_text)) user_box.change_bg_image(WOOD) user_box.add_frame(FRAME) self.sprite_grp.add(user_box)
def _init_your_turn(self): rct = RectLabel(880, 600, 250, 50, background=Color.ORANGE, txt_obj=Text(pygame.font.SysFont('Agency FB', 30), "YOUR TURN", Color.GREEN2)) rct.change_bg_image(WOOD) rct.add_frame(FRAME) return rct
def _init_text_box(self, color: Color): box_size = (self.txt_pos[2], self.txt_pos[3]) user_box = RectLabel( self.txt_pos[0], self.txt_pos[1], box_size[0], box_size[1], color, 0, Text(pygame.font.SysFont('Agency FB', 27), self.player_username, color)) user_box.change_bg_image(MEDIA_CONSTS.WOOD) user_box.add_frame(MEDIA_CONSTS.FRAME) return user_box
def _init_ip_addr(self): if Networking.get_instance().is_host: ip_addr = f"Your IP address: {Networking.get_instance().get_ip()}" label_width = 400 label_left = (pygame.display.get_surface().get_size()[0] / 2) - (label_width / 2) ip_addr_label = RectLabel(label_left, 20, label_width, 50, (255, 255, 255), txt_obj=(Text( pygame.font.SysFont('Agency FB', 26), ip_addr, Color.GREEN2))) ip_addr_label.change_bg_image(MEDIA_CONSTS.WOOD) ip_addr_label.add_frame(MEDIA_CONSTS.FRAME) #ip_addr_label.set_transparent_background(True) self.sprite_grp.add(ip_addr_label)
class VehiclePlacementController(Controller): """Class for controlling inputs during the placing vehicles phase. Displays prompts.""" _instance = None def __init__(self, current_player: PlayerModel): super().__init__(current_player) if VehiclePlacementController._instance: self._current_player = current_player # raise Exception(f"{VehiclePlacementController.__name__} is a singleton!") self.choose_engine_prompt = RectLabel( 500, 30, 350, 75, Color.GREY, 0, Text(pygame.font.SysFont('Agency FB', 30), "Choose Engine Position", Color.GREEN2)) self.choose_engine_prompt.change_bg_image(WOOD) self.choose_engine_prompt.add_frame(FRAME) self.choose_ambulance_prompt = RectLabel( 500, 30, 350, 75, Color.GREY, 0, Text(pygame.font.SysFont('Agency FB', 30), "Choose Ambulance Position", Color.GREEN2)) self.choose_ambulance_prompt.change_bg_image(WOOD) self.choose_ambulance_prompt.add_frame(FRAME) self.wait_prompt = RectLabel( 500, 580, 350, 75, Color.GREY, 0, Text(pygame.font.SysFont('Agency FB', 30), "Host Is Placing Vehicles...", Color.GREEN2)) self.wait_prompt.change_bg_image(WOOD) self.wait_prompt.add_frame(FRAME) self.game_board_sprite = GameBoard.instance() self.ambulance_placed = False self.engine_placed = False VehiclePlacementController._instance = self @classmethod def instance(cls): return cls._instance def run_checks(self, tile_model: TileModel) -> bool: game: GameStateModel = GameStateModel.instance() if game.state != GameStateEnum.PLACING_VEHICLES: return False if not Networking.get_instance().is_host: return False if tile_model.space_kind == SpaceKindEnum.INDOOR: return False return True def send_event_and_close_menu(self, tile_model: TileModel, menu_to_close: Interactable): game_board: GameBoardModel = GameStateModel.instance().game_board spot_list = game_board.engine_spots if self.ambulance_placed else game_board.ambulance_spots parking_spot = [spot for spot in spot_list if tile_model in spot] if not parking_spot: return parking_spot = parking_spot[0] vehicle = game_board.engine if self.ambulance_placed else game_board.ambulance event = VehiclePlacedEvent(vehicle, parking_spot) if Networking.get_instance().is_host: Networking.get_instance().send_to_all_client(event) else: Networking.get_instance().client.send(event) if not self.ambulance_placed: self.ambulance_placed = True elif not self.engine_placed: self.engine_placed = True def _check_highlight(self, tile_model: TileModel, vehicle_type: str): if vehicle_type == "AMBULANCE": return tile_model.space_kind == SpaceKindEnum.AMBULANCE_PARKING elif vehicle_type == "ENGINE": return tile_model.space_kind == SpaceKindEnum.ENGINE_PARKING def _apply_highlight(self, vehicle_type: str): game_state = GameStateModel.instance() for i in range(len(self.game_board_sprite.grid.grid)): for j in range(len(self.game_board_sprite.grid.grid[i])): tile_model = game_state.game_board.get_tile_at(j, i) tile_sprite = self.game_board_sprite.grid.grid[i][j] success = self._check_highlight(tile_model, vehicle_type) if success and not tile_sprite.highlight_color: tile_sprite.highlight_color = Color.GREEN elif not success: tile_sprite.highlight_color = None def process_input(self, tile_sprite: TileSprite): game_state: GameStateModel = GameStateModel.instance() tile_model = game_state.game_board.get_tile_at(tile_sprite.row, tile_sprite.column) if not self.run_checks(tile_model): return self.send_event_and_close_menu(tile_model, None) def enable_prompts(self): if Networking.get_instance().is_host: self.game_board_sprite.top_ui.add(self.choose_engine_prompt) self.game_board_sprite.top_ui.add(self.choose_ambulance_prompt) else: self.game_board_sprite.top_ui.add(self.wait_prompt) def update(self, event_queue: EventQueue): game: GameStateModel = GameStateModel.instance() if not game.state == GameStateEnum.PLACING_VEHICLES: return if self.engine_placed: self.choose_engine_prompt.kill() if self.ambulance_placed: self.choose_ambulance_prompt.kill() ambulance: VehicleModel = GameStateModel.instance( ).game_board.ambulance engine: VehicleModel = GameStateModel.instance().game_board.engine if ambulance.orientation != VehicleOrientationEnum.UNSET and engine.orientation != VehicleOrientationEnum.UNSET: self.wait_prompt.kill() self.choose_ambulance_prompt.kill() self.choose_engine_prompt.kill() vehicle_type = "ENGINE" if self.ambulance_placed else "AMBULANCE" self._apply_highlight(vehicle_type)
class ChooseStartingPositionController(Controller): _instance = None def __init__(self, current_player: PlayerModel): super().__init__(current_player) if ChooseStartingPositionController._instance: self._current_player = current_player # raise Exception("ChooseStartingPositionController is a singleton") self.current_player = current_player self.game_board_sprite = GameBoard.instance() self.choose_prompt = RectLabel( 500, 30, 350, 75, Color.GREY, 0, Text(pygame.font.SysFont('Agency FB', 30), "Choose Starting Position", Color.GREEN2)) self.choose_prompt.change_bg_image(WOOD) self.choose_prompt.add_frame(FRAME) self.wait_prompt = RectLabel( 500, 400, 300, 50, Color.GREY, 0, Text(pygame.font.SysFont('Agency FB', 30), "Wait for your turn!", Color.GREEN2)) self.wait_prompt.change_bg_image(WOOD) self.wait_prompt.add_frame(FRAME) self.game_board_sprite.top_ui.add(self.choose_prompt) self.game_board_sprite.top_ui.add(self.wait_prompt) ChooseStartingPositionController._instance = self @classmethod def instance(cls): return cls._instance def _apply_hover(self): for i in range(len(self.game_board_sprite.grid.grid)): for j in range(len(self.game_board_sprite.grid.grid[i])): tile_model = GameStateModel.instance().game_board.get_tile_at( j, i) tile_sprite = self.game_board_sprite.grid.grid[i][j] success = self.run_checks(tile_model) if success and not tile_sprite.highlight_color: tile_sprite.highlight_color = Color.GREEN elif not success: tile_sprite.highlight_color = None def send_event_and_close_menu(self, tile_model: TileModel, menu_to_close: Interactable): pass def run_checks(self, tile_model: TileModel) -> bool: if GameStateModel.instance().state != GameStateEnum.PLACING_PLAYERS: return False if self.current_player != GameStateModel.instance().players_turn: return False # Check if any Players are in this tile if GameStateModel.instance().get_players_on_tile( tile_model.row, tile_model.column): return False if tile_model.space_kind == SpaceKindEnum.INDOOR: return False return True def process_input(self, tile_sprite: TileSprite): if not GameStateModel.instance().players_turn.has_pos: tile_model = GameStateModel.instance().game_board.get_tile_at( tile_sprite.row, tile_sprite.column) if not self.run_checks(tile_model): return event = ChooseStartingPositionEvent(tile_model.row, tile_model.column) self.choose_prompt.kill() if Networking.get_instance().is_host: Networking.get_instance().send_to_all_client(event) else: Networking.get_instance().send_to_server(event) def update(self, event_queue: EventQueue): if self.current_player == GameStateModel.instance().players_turn: self.wait_prompt.kill() if GameStateModel.instance().state == GameStateEnum.PLACING_PLAYERS: self._apply_hover()
class PlayerBox(PlayerObserver): def __init__(self, text_position, background_position, username: str, player: PlayerModel, color: Color): super().__init__() self._game: GameStateModel = GameStateModel.instance() self._assoc_player = player self._assoc_player.add_observer(self) self.player_username = username self.txt_pos = text_position self.background_position = background_position self.text_box = self._init_text_box(color) self.background = RectLabel( self.background_position[0], self.background_position[1], self.background_position[2], self.background_position[3], ) self.background.change_bg_image(MEDIA_CONSTS.WOOD) self.background.add_frame( self.get_path_from_character_enum(self._assoc_player.role)) self.background.add_frame(MEDIA_CONSTS.FRAME) def delete_class(self): self._assoc_player.remove_observer(self) def _init_text_box(self, color: Color): box_size = (self.txt_pos[2], self.txt_pos[3]) user_box = RectLabel( self.txt_pos[0], self.txt_pos[1], box_size[0], box_size[1], color, 0, Text(pygame.font.SysFont('Agency FB', 27), self.player_username, color)) user_box.change_bg_image(MEDIA_CONSTS.WOOD) user_box.add_frame(MEDIA_CONSTS.FRAME) return user_box def get_path_from_character_enum(self, enum: PlayerRoleEnum): if enum == PlayerRoleEnum.CAFS: return MEDIA_CONSTS.CAFS_FIREFIGHTER elif enum == PlayerRoleEnum.CAPTAIN: return MEDIA_CONSTS.FIRE_CAPTAIN elif enum == PlayerRoleEnum.GENERALIST: return MEDIA_CONSTS.GENERALIST elif enum == PlayerRoleEnum.DRIVER: return MEDIA_CONSTS.DRIVER_OPERATOR elif enum == PlayerRoleEnum.HAZMAT: return MEDIA_CONSTS.HAZMAT_TECHNICIAN elif enum == PlayerRoleEnum.IMAGING: return MEDIA_CONSTS.IMAGING_TECHNICIAN elif enum == PlayerRoleEnum.PARAMEDIC: return MEDIA_CONSTS.PARAMEDIC elif enum == PlayerRoleEnum.RESCUE: return MEDIA_CONSTS.RESCUE_SPECIALIST elif enum == PlayerRoleEnum.FAMILY: return MEDIA_CONSTS.FAMILY elif enum == PlayerRoleEnum.DOGE: return MEDIA_CONSTS.DOGE elif enum == PlayerRoleEnum.VETERAN: return MEDIA_CONSTS.VETERAN def draw(self, screen): self.text_box.draw(screen) if self.background: self.background.draw(screen) self.background.change_bg_image(MEDIA_CONSTS.WOOD) self.background.add_frame( self.get_path_from_character_enum(self._assoc_player.role)) self.background.add_frame(MEDIA_CONSTS.FRAME) def player_status_changed(self, status: PlayerStatusEnum): pass def player_ap_changed(self, updated_ap: int): pass def player_special_ap_changed(self, updated_ap: int): pass def player_position_changed(self, row: int, column: int): pass def player_wins_changed(self, wins: int): pass def player_losses_changed(self, losses: int): pass def player_carry_changed(self, carry): pass def player_leading_victim_changed(self, leading_victim): pass def player_role_changed(self, role: PlayerRoleEnum): if self._game.state == GameStateEnum.READY_TO_JOIN: logger.info(f"new role: {role}") role_path = self.get_path_from_character_enum(role) logger.info(f"Role Path is: {role_path}") self.background = (RectLabel(self.background_position[0], self.background_position[1], self.background_position[2], self.background_position[3], role_path))
class DodgePrompt(object): """Prompt for the player deciding whether to dodge or not.""" def __init__(self): self.bg = pygame.image.load(WOOD) self.frame = pygame.image.load(FRAME) self.frame = pygame.transform.scale(self.frame, (400, 100)) self.accept_button = RectButton( 550 - 75, 310, 75, 50, Color.ORANGE, 0, Text(pygame.font.SysFont('Agency FB', 25), "Accept", Color.GREEN2)) self.accept_button.change_bg_image(WOOD) self.accept_button.add_frame(FRAME) self.deny_button = RectButton( 550 + 200, 310, 75, 50, Color.ORANGE, 0, Text(pygame.font.SysFont('Agency FB', 25), "Deny", Color.GREEN2)) self.deny_button.change_bg_image(WOOD) self.deny_button.add_frame(FRAME) self.accept_button.on_click(self._accept_on_click) self.deny_button.on_click(self._deny_on_click) self.background = RectLabel( 550, 300, 200, 75, Color.GREY, 0, Text(pygame.font.SysFont('Agency FB', 25), "Dodge?", Color.GREEN2)) self.background.change_bg_image(WOOD) self.background.add_frame(FRAME) self.enabled = False self.disable() def enable(self): self.deny_button.enable() self.accept_button.enable() self.accept_button.on_click(self._accept_on_click) self.deny_button.on_click(self._deny_on_click) self.enabled = True def disable(self): self.deny_button.disable() self.accept_button.disable() self.accept_button.on_click(None) self.deny_button.on_click(None) self.enabled = False def _send_reply_event(self, reply: bool): if Networking.get_instance().is_host: Networking.get_instance().send_to_all_client( DodgeReplyEvent(reply)) else: Networking.get_instance().send_to_server(DodgeReplyEvent(reply)) def _deny_on_click(self): self.disable() self._send_reply_event(False) def _accept_on_click(self): self.disable() self._send_reply_event(True) def update(self, event_queue: EventQueue): self.background.update(event_queue) self.accept_button.update(event_queue) self.deny_button.update(event_queue) def draw(self, screen): if self.enabled: self.background.draw(screen) self.accept_button.draw(screen) self.deny_button.draw(screen)
class FireDeckGunController(Controller): _instance = None def __init__(self, current_player: PlayerModel): super().__init__(current_player) if FireDeckGunController._instance: self._current_player = current_player # raise Exception("Victim Controller is a singleton") self._game: GameStateModel = GameStateModel.instance() self.player = current_player self.board: GameBoardModel = self._game.game_board self.engine = self.board.engine FireDeckGunController._instance = self self.label = None self.input1 = None self.input2 = None self.input3 = None self.input4 = None self.max_input = 0 @classmethod def instance(cls): return cls._instance def process_input(self, tile_sprite: TileSprite): assoc_model = self.board.get_tile_at(tile_sprite.row, tile_sprite.column) button = None if self.run_checks(assoc_model): button = tile_sprite.fire_deck_gun_button if button: tile_sprite.fire_deck_gun_button.enable() if self._current_player.role == PlayerRoleEnum.DRIVER: button.on_click(self.driver_menu_popup, assoc_model) else: button.on_click(self.send_event_and_close_menu, assoc_model, button) else: tile_sprite.fire_deck_gun_button.disable() def run_checks(self, tile_model: TileModel) -> bool: """ Determines whether or not it is possible to perform this event. :return: True if it possible to perform this event. False otherwise. """ # Doge cannot fire the deck gun if self.player.role == PlayerRoleEnum.DOGE: return False if not self.player == GameStateModel.instance().players_turn: return False ap_deduct = 2 if self.player.role == PlayerRoleEnum.DRIVER else 4 if not TurnEvent.has_required_AP(self.player.ap, ap_deduct): return False # If the player is not located in the # same space as the engine, they cannot # fire the deck gun. engine_orient = self.engine.orientation if engine_orient == VehicleOrientationEnum.HORIZONTAL: on_first_spot = self.player.row == self.engine.row and self.player.column == self.engine.column on_second_spot = self.player.row == self.engine.row and self.player.column == self.engine.column + 1 if not on_first_spot and not on_second_spot: return False elif engine_orient == VehicleOrientationEnum.VERTICAL: on_first_spot = self.player.row == self.engine.row and self.player.column == self.engine.column on_second_spot = self.player.row == self.engine.row + 1 and self.player.column == self.engine.column if not on_first_spot and not on_second_spot: return False engine_quadrant = self._determine_quadrant(self.engine.row, self.engine.column) tile_input_quadrant = self._determine_quadrant(tile_model.row, tile_model.column) # If there are players present in the # quadrant, the deck gun cannot be fired. # tile input gotta be on quadrant adjacent to engine if self._are_players_in_quadrant( engine_quadrant) or tile_input_quadrant != engine_quadrant: return False return True @staticmethod def _determine_quadrant(row, column) -> QuadrantEnum: """ Determines the quadrant to which the row and column belong to. :param row: :param column: :return: Quadrant in which the row and column are located. """ if row < 4 and column < 5: return QuadrantEnum.TOP_LEFT elif row < 4 and column >= 5: return QuadrantEnum.TOP_RIGHT elif row >= 4 and column < 5: return QuadrantEnum.BOTTOM_LEFT else: return QuadrantEnum.BOTTOM_RIGHT @staticmethod def _determine_quadrant_player(row, column) -> QuadrantEnum: """ Determines the quadrant to which the row and column belong to. :param row: :param column: :return: Quadrant in which the row and column are located. """ if 4 > row > 0 and 5 > column > 0: return QuadrantEnum.TOP_LEFT elif 4 > row > 0 and 5 <= column < 9: return QuadrantEnum.TOP_RIGHT elif 4 <= row < 7 and 5 > column > 0: return QuadrantEnum.BOTTOM_LEFT elif 4 <= row < 7 and 5 <= column < 9: return QuadrantEnum.BOTTOM_RIGHT def _are_players_in_quadrant(self, quadrant: QuadrantEnum) -> bool: """ Determines whether there are any players in the given quadrant. :param quadrant: Quadrant that we are interested in. :return: True if there are players in the quadrant, False otherwise. """ for player in self._game.players: logger.info( f"Player assoc_quadrant: {self._determine_quadrant_player(player.row, player.column)}" ) logger.info( f"Player row: {player.row}, Player column: {player.column}") logger.info(f"Quadrant to compare: {quadrant}") if quadrant == self._determine_quadrant_player( player.row, player.column): return True return False def send_event_and_close_menu(self, tile_model: TileModel, menu_to_close: Interactable, row: int = -1, column: int = -1): event = FireDeckGunEvent(row=row, column=column) if not self.run_checks(tile_model): menu_to_close.disable() return if Networking.get_instance().is_host: Networking.get_instance().send_to_all_client(event) else: Networking.get_instance().client.send(event) if menu_to_close: menu_to_close.disable() def _set_target_tile(self, row: int = -1, column: int = -1): """ Set the tile which will be the target for the firing of the deck gun. :return: """ engine_quadrant = self._determine_quadrant(self.engine.row, self.engine.column) if row == -1: target_row = GameStateModel.instance().roll_red_dice() else: target_row = row if column == -1: target_column = GameStateModel.instance().roll_black_dice() else: target_column = column target_quadrant = self._determine_quadrant(target_row, target_column) # If the roll gives a tile in the engine's # quadrant, that will become the target tile. if target_quadrant == engine_quadrant: target_tile = GameStateModel.instance().game_board.get_tile_at( target_row, target_column) return target_tile else: # Flipping the red dice involves # subtracting the roll value from 7. flipped_row = 7 - target_row # Try out the following combinations # and see if any of them are in the # engine's quadrant: # 1. flipping the row, same column # 2. same row, flipping the column # 3. flipping the row, flipping the column new_target_quadrant = self._determine_quadrant( flipped_row, target_column) if new_target_quadrant == engine_quadrant: target_tile = GameStateModel.instance().game_board.get_tile_at( flipped_row, target_column) return target_tile flipped_column = GameStateModel.instance( ).determine_black_dice_opposite_face(target_column) new_target_quadrant = self._determine_quadrant( target_row, flipped_column) if new_target_quadrant == engine_quadrant: target_tile = GameStateModel.instance().game_board.get_tile_at( target_row, flipped_column) return target_tile new_target_quadrant = self._determine_quadrant( flipped_row, flipped_column) if new_target_quadrant == engine_quadrant: target_tile = GameStateModel.instance().game_board.get_tile_at( flipped_row, flipped_column) return target_tile # $$$$$$$$$$$$$$$$$ # Shouldn't be able to reach this point!! # One of the cases above should have worked. # $$$$$$$$$$$$$$$$$ logger.error("Possible issue with dice flipping! Stop!!") raise FlippingDiceProblemException() def driver_menu_popup(self, tile_model: TileModel): decision: int = 0 targetTile: TileModel = self._set_target_tile() red_dice = targetTile.row black_dice = targetTile.column boardSprite: GameBoard = GameBoard.instance().top_ui self.label = RectLabel( 200, 400, 600, 200, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), f"Roll: {red_dice}, {black_dice}", Color.GREEN2)) self.label.change_bg_image(WOOD) self.label.add_frame(FRAME) self.input1 = RectButton( 200, 350, 150, 50, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), "Accept Roll", Color.GREEN2)) self.input1.change_bg_image(WOOD) self.input1.add_frame(FRAME) self.input2 = RectButton( 350, 350, 150, 50, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), "Re-Roll Black Dice", Color.GREEN2)) self.input2.change_bg_image(WOOD) self.input2.add_frame(FRAME) self.input3 = RectButton( 500, 350, 150, 50, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), "Re-Roll Red Dice", Color.GREEN2)) self.input3.change_bg_image(WOOD) self.input3.add_frame(FRAME) self.input4 = RectButton( 650, 350, 150, 50, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), "Re-Roll Both Die", Color.GREEN2)) self.input4.change_bg_image(WOOD) self.input4.add_frame(FRAME) self.input1.on_click(self.input1_process, tile_model, red_dice, black_dice) self.input2.on_click(self.input2_process, tile_model, red_dice, black_dice) self.input3.on_click(self.input3_process, tile_model, red_dice, black_dice) self.input4.on_click(self.input4_process, tile_model, red_dice, black_dice) boardSprite.add(self.label) boardSprite.add(self.input1) boardSprite.add(self.input2) boardSprite.add(self.input3) boardSprite.add(self.input4) def input1_process(self, tile: TileModel, red_dice: int, black_dice: int): self.kill_all() self.max_input = 0 self.send_event_and_close_menu(tile, self.input1, red_dice, black_dice) def input2_process(self, tile: TileModel, red_dice: int, black_dice: int): self.max_input += 1 board_sprite: GameBoard = GameBoard.instance().top_ui self.kill_all() new_tile: TileModel = self._set_target_tile(red_dice) if self.max_input == 2: self.max_input = 0 self.send_event_and_close_menu(tile, self.input1, new_tile.row, new_tile.column) else: black_dice = new_tile.column self.label = RectLabel( 200, 400, 600, 200, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), f"Roll: {red_dice}, {black_dice}", Color.GREEN2)) self.label.change_bg_image(WOOD) self.label.add_frame(FRAME) self.input1 = RectButton( 200, 350, 150, 50, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), "Accept Roll", Color.GREEN2)) self.input1.change_bg_image(WOOD) self.input1.add_frame(FRAME) self.input3 = RectButton( 350, 350, 150, 50, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), "Re-Roll Red Dice", Color.GREEN2)) self.input3.change_bg_image(WOOD) self.input3.add_frame(FRAME) self.input1.on_click(self.input1_process, tile, red_dice, new_tile.column) self.input3.on_click(self.input3_process, tile, red_dice, new_tile.column) board_sprite.add(self.label) board_sprite.add(self.input1) board_sprite.add(self.input3) def input3_process(self, tile: TileModel, red_dice: int, black_dice: int): self.max_input += 1 board_sprite: GameBoard = GameBoard.instance().top_ui self.kill_all() new_tile: TileModel = self._set_target_tile(-1, black_dice) if self.max_input == 2: self.max_input = 0 self.send_event_and_close_menu(tile, self.input1, new_tile.row, new_tile.column) else: red_dice = new_tile.row self.label = RectLabel( 200, 400, 600, 200, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), f"Roll: {red_dice}, {black_dice}", Color.GREEN2)) self.label.change_bg_image(WOOD) self.label.add_frame(FRAME) self.input1 = RectButton( 200, 350, 150, 50, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), "Accept Roll", Color.GREEN2)) self.input1.change_bg_image(WOOD) self.input1.add_frame(FRAME) self.input2 = RectButton( 350, 350, 150, 50, Color.BLACK, 0, Text(pygame.font.SysFont('Agency FB', 25), "Re-Roll Black Dice", Color.GREEN2)) self.input2.change_bg_image(WOOD) self.input2.add_frame(FRAME) self.input1.on_click(self.input1_process, tile, new_tile.row, black_dice) self.input2.on_click(self.input2_process, tile, new_tile.row, black_dice) board_sprite.add(self.label) board_sprite.add(self.input1) board_sprite.add(self.input2) def input4_process(self, tile: TileModel, red_dice: int, black_dice: int): self.kill_all() new_tile: TileModel = self._set_target_tile() self.send_event_and_close_menu(tile, self.input1, new_tile.row, new_tile.column) def kill_all(self): self.input1.kill() self.input2.kill() self.input3.kill() self.input4.kill() self.label.kill()
class CommandNotification(object): """Displays the command status to the targeted players (source and target)""" def __init__(self): self._source = None self._target = None self._notification = RectLabel( 500, 0, 350, 75, Color.GREY, 0, Text(pygame.font.SysFont('Agency FB', 30), f"Commanding: None", Color.GREEN2)) self._notification.change_bg_image(WOOD) self._notification.add_frame(FRAME) self._wait_command = RectLabel( 500, 400, 300, 50, Color.GREY, 0, Text(pygame.font.SysFont('Agency FB', 30), f"Commanded by: None", Color.GREEN2)) self._wait_command.change_bg_image(WOOD) self._wait_command.add_frame(FRAME) self._init_end_command_btn() self._is_source = False self._is_target = False def _init_end_command_btn(self): # End command button self._end_command_btn = RectButton( 1080, 450, 200, 50, background=Color.ORANGE, txt_obj=Text(pygame.font.SysFont('Agency FB', 23), "END COMMAND", Color.GREEN2)) self._end_command_btn.change_bg_image(WOOD) self._end_command_btn.add_frame(FRAME) self._end_command_btn.on_click(self.end_command) def end_command(self): event = StopCommandEvent(self._source) if Networking.get_instance().is_host: Networking.get_instance().send_to_all_client(event) else: Networking.get_instance().send_to_server(event) @property def command(self) -> Tuple[PlayerModel, PlayerModel]: return self._source, self._target @command.setter def command(self, command: Tuple[PlayerModel, PlayerModel]): (self._source, self._target) = command source_msg = "Commanding: None" target_msg = "Commanded by: None" if self._target: source_msg = f"Commanding: {self._target.nickname}" if self._source: target_msg = f"Commanded by: {self._source.nickname}" self._notification.change_text( Text(pygame.font.SysFont('Agency FB', 30), source_msg, Color.ORANGE)) self._notification.change_bg_image(WOOD) self._notification.add_frame(FRAME) self._wait_command.change_text( Text(pygame.font.SysFont('Agency FB', 30), target_msg, Color.ORANGE)) self._wait_command.change_bg_image(WOOD) self._wait_command.add_frame(FRAME) @property def is_source(self) -> bool: return self._is_source @is_source.setter def is_source(self, source: bool): self._is_source = source @property def is_target(self) -> bool: return self._is_target @is_target.setter def is_target(self, target: bool): self._is_target = target def update(self, event_queue: EventQueue): if self.is_source: self._notification.update(event_queue) self._end_command_btn.update(event_queue) elif self.is_target: self._wait_command.update(event_queue) def draw(self, screen): if self.is_source: self._notification.draw(screen) self._end_command_btn.draw(screen) elif self.is_target: self._wait_command.draw(screen)
class PermissionPrompt(object): """Prompt for the player deciding whether to allow to be commanded or not.""" def __init__(self): self.accept_button = RectButton( 500 - 75, 310, 75, 50, Color.ORANGE, 0, Text(pygame.font.SysFont('Agency FB', 20), "Accept", Color.GREEN2)) self.accept_button.change_bg_image(WOOD) self.accept_button.add_frame(FRAME) self.deny_button = RectButton( 500 + 300, 310, 75, 50, Color.ORANGE, 0, Text(pygame.font.SysFont('Agency FB', 20), "Deny", Color.GREEN2)) self.deny_button.change_bg_image(WOOD) self.deny_button.add_frame(FRAME) self.accept_button.on_click(self._accept_on_click) self.deny_button.on_click(self._deny_on_click) self._source = None self._target = None self.background = RectLabel( 500, 300, 300, 75, Color.GREY, 0, Text(pygame.font.SysFont('Agency FB', 20), "Permission?", Color.GREEN2)) self.background.change_bg_image(WOOD) self.background.add_frame(FRAME) self._enabled = False def _send_reply_event(self, reply: bool): if Networking.get_instance().is_host: Networking.get_instance().send_to_all_client( PermissionReplyEvent(reply, self._source, self._target)) else: Networking.get_instance().send_to_server( PermissionReplyEvent(reply, self._source, self._target)) def _deny_on_click(self): self.enabled = False self._send_reply_event(False) def _accept_on_click(self): self.enabled = False self._send_reply_event(True) def update(self, event_queue: EventQueue): if self._enabled: self.background.update(event_queue) self.accept_button.update(event_queue) self.deny_button.update(event_queue) def draw(self, screen): if self._enabled: self.background.draw(screen) self.accept_button.draw(screen) self.deny_button.draw(screen) @property def enabled(self) -> bool: return self._enabled @enabled.setter def enabled(self, enable: bool): self._enabled = enable @property def command(self) -> Tuple[PlayerModel, PlayerModel]: return self._source, self._target @command.setter def command(self, command: Tuple[PlayerModel, PlayerModel]): self._source = command[0] self._target = command[1] self.background.change_text( Text(pygame.font.SysFont('Agency FB', 20), f"{self._source.nickname} wants to command you", Color.GREEN2)) self.background.change_bg_image(WOOD) self.background.add_frame(FRAME)