예제 #1
0
class DoorSprite(pygame.sprite.Sprite, DoorObserver):
    def __init__(self, door_model: DoorModel, orientation: str,
                 tile_sprite: TileSprite, tile_model: TileModel,
                 id: Tuple[int, int, str]):
        super().__init__()
        self.orientation = orientation
        self._game: GameStateModel = GameStateModel.instance()
        self._current_player = self._game.players_turn
        self._button = None
        self.tile_model = tile_model
        self.id = id
        self.door_model = door_model
        self.door_model.add_observer(self)

        self.open = self.door_model.door_status == DoorStatusEnum.OPEN
        self.closed = self.door_model.door_status == DoorStatusEnum.CLOSED
        self.destroyed = self.door_model.door_status == DoorStatusEnum.DESTROYED

        self.marker = None
        self.tile_sprite = tile_sprite
        self._prev_x = self.tile_sprite.rect.x
        self._prev_y = self.tile_sprite.rect.y
        self.button_input = RectButton(
            self.tile_sprite.rect.x + 100, self.tile_sprite.rect.y + 100, 100,
            25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Interact",
                 Color.GREEN2))
        pygame.draw.rect(self.button_input.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)
        self.button_input.disable()
        self.menu_shown = False

    @property
    def direction(self) -> str:
        return self.id[2]

    @property
    def player(self) -> PlayerModel:
        return self._current_player

    @property
    def button(self):
        return self._button

    @button.setter
    def button(self, button):
        self._button = button

    def update(self, event_queue):
        diff_x = self.tile_sprite.rect.x - self._prev_x
        diff_y = self.tile_sprite.rect.y - self._prev_y
        self._button.rect.move_ip((diff_x, diff_y))
        self._prev_x = self.tile_sprite.rect.x
        self._prev_y = self.tile_sprite.rect.y
        self.button_input.rect.x = self.tile_sprite.rect.x + 100
        self.button_input.rect.y = self.tile_sprite.rect.y + 100

        for event in event_queue:
            if event.type == pygame.MOUSEBUTTONUP:
                if not ((self.button_input.rect.x <= pygame.mouse.get_pos()[0]
                         <= self.button_input.rect.x + 100) and
                        (self.button_input.rect.y <= pygame.mouse.get_pos()[1]
                         <= self.button_input.rect.y + 25)):
                    self.button_input.disable()

        self._button.update(event_queue)
        self.button_input.update(event_queue)

    def door_status_changed(self, status: DoorStatusEnum):
        if status == DoorStatusEnum.DESTROYED:
            self.destroyed = True
            self.open = False
            self.closed = False
        elif status == DoorStatusEnum.CLOSED:
            self.closed = True
            self.open = False
            self.destroyed = False
        elif status == DoorStatusEnum.OPEN:
            self.open = True
            self.closed = False
            self.destroyed = False
        else:
            raise Exception("Door status ERROR")

    def draw(self, screen):
        self.button.draw(screen)
        x_offset1 = 0
        y_offset1 = 0

        if self.menu_shown:
            if self.button_input.enabled:
                screen.blit(self.button_input.image, self.button_input.rect)

        if self.orientation == "vertical":
            x_offset1 = -22
            y_offset1 = 40

        if self.orientation == "horizontal":
            x_offset1 = 34
            y_offset1 = -18

        if self.destroyed:
            self.marker = RectLabel(self.button.rect.x + x_offset1,
                                    self.button.rect.y + y_offset1, 50, 50,
                                    "media/Threat_Markers/damageMarker.png")
            self.marker.draw(screen)
        if self.open:
            self.marker = RectLabel(self.button.rect.x + x_offset1,
                                    self.button.rect.y + y_offset1, 50, 50,
                                    "media/Door_Markers/Open_Door.png")
            self.marker.draw(screen)
        if self.closed:
            self.marker = RectLabel(self.button.rect.x + x_offset1,
                                    self.button.rect.y + y_offset1, 50, 50,
                                    "media/Door_Markers/Closed_Door.png")
            self.marker.draw(screen)
예제 #2
0
class LobbyScene(GameStateObserver):
    def __init__(self, screen, current_player: PlayerModel):
        super().__init__()
        self._current_player = current_player
        self._game = GameStateModel.instance()
        self.player_boxes = []

        if Networking.get_instance().is_host:
            self._current_player.color = Color.BLUE
            self._game.host.color = Color.BLUE
            self._current_player.status = PlayerStatusEnum.READY

        self._player_count = len(self._game.players)
        self.isReady = False
        self.resolution = (1280, 700)
        self.sprite_grp = pygame.sprite.Group()
        self.players_not_ready_prompt = None
        self._init_all()

        if self._game.rules == GameKindEnum.EXPERIENCED:
            self.buttonSelChar.on_click(
                EventQueue.post, CustomEvent(ChangeSceneEnum.CHARACTERSCENE))
        if Networking.get_instance().is_host:
            self._current_player.status = PlayerStatusEnum.READY
            self.isReady = True
            self.start_button.on_click(self.start_game)
            self.start_button.disable()
            if self._game.rules == GameKindEnum.EXPERIENCED and self._current_player.role == PlayerRoleEnum.FAMILY:
                self._current_player.status = PlayerStatusEnum.NOT_READY
        else:
            self._current_player.status = PlayerStatusEnum.NOT_READY
            self.buttonReady.on_click(self.set_ready)
        self.buttonBack.on_click(self.go_back)

    @staticmethod
    def go_back():
        if Networking.get_instance().is_host:
            next_scene = ChangeSceneEnum.SETMAXPLAYERSCENE
        else:
            next_scene = ChangeSceneEnum.JOINSCENE
        Networking.get_instance().disconnect()
        EventQueue.post(CustomEvent(next_scene))

    def start_game(self):
        """Callback for when the host tries to start the game."""
        game = GameStateModel.instance()
        players_ready = len([
            player for player in game.players
            if player.status == PlayerStatusEnum.READY
        ])

        if not self._game.rules == GameKindEnum.FAMILY:
            if any(player.role == PlayerRoleEnum.FAMILY
                   for player in game.players):
                return

        if not players_ready == game.max_players:
            self.not_enough_players_ready_prompt()
            return
        # Perform the start game hook in Networking (ie. stop accepting new connections and kill broadcast)

        if Networking.get_instance().is_host:
            # Kill the broadcast
            for box in self.player_boxes:
                box.delete_class()
            Networking.get_instance().send_to_all_client(StartGameEvent())

    def set_ready(self):
        """Set the status of the current player to ready."""
        if not self.isReady:
            if not (self._game.rules == GameKindEnum.FAMILY and self._current_player.role == PlayerRoleEnum.FAMILY) \
                    or self._game.rules == GameKindEnum.FAMILY:
                self.isReady = True
                self.sprite_grp.remove(self.buttonReady)
                box_size = (130, 48)
                self.buttonReady = RectButton(
                    1050, 575, box_size[0], box_size[1], Color.BLACK, 0,
                    Text(pygame.font.SysFont('Agency FB', 25), "Ready",
                         Color.GREEN))
                self.buttonReady.change_bg_image(MEDIA_CONSTS.WOOD)
                self.buttonReady.add_frame(MEDIA_CONSTS.FRAME)
                self.buttonReady.on_click(self.set_ready)
                self.sprite_grp.add(self.buttonReady)
                self._current_player.status = PlayerStatusEnum.READY
                event = ReadyEvent(self._current_player, True)

                if self._current_player.ip == GameStateModel.instance(
                ).host.ip:
                    event.execute()
                    Networking.get_instance().send_to_all_client(event)
                else:
                    Networking.get_instance().send_to_server(event)
        else:
            self.isReady = False
            self.sprite_grp.remove(self.buttonReady)
            box_size = (130, 48)
            self.buttonReady = RectButton(
                1050, 575, box_size[0], box_size[1], Color.BLACK, 0,
                Text(pygame.font.SysFont('Agency FB', 25), "Not Ready",
                     Color.GREY))
            self.buttonReady.change_bg_image(MEDIA_CONSTS.WOOD)
            self.buttonReady.add_frame(MEDIA_CONSTS.FRAME)
            self.buttonReady.on_click(self.set_ready)
            self.sprite_grp.add(self.buttonReady)
            self._current_player.status = PlayerStatusEnum.NOT_READY
            event = ReadyEvent(self._current_player, False)
            if self._current_player.ip == GameStateModel.instance().host.ip:
                event.execute()
                Networking.get_instance().send_to_all_client(event)
            else:
                Networking.get_instance().send_to_server(event)

    def _init_all(self, reuse=False):
        self._init_background()
        self._init_ip_addr()
        self.chat_box = ChatBox(self._current_player)

        if not reuse:
            self._init_btn_back(20, 20, "Exit", MEDIA_CONSTS.WOOD,
                                Color.GREEN2)

            if self._current_player.ip == GameStateModel.instance().host.ip:
                self._init_start_game_button()
            else:
                # Ready button is grey at first
                self._init_ready(1050, 575, "Not Ready", Color.GREY,
                                 Color.BLACK)

            if not self._game.rules == GameKindEnum.FAMILY:
                self._init_selec_char(1050, 475, "Select Character",
                                      Color.STANDARDBTN, Color.GREEN2)
        else:
            if not self._game.rules == GameKindEnum.FAMILY:
                self.sprite_grp.add(self.buttonSelChar)
            if self._current_player.ip == GameStateModel.instance().host.ip:
                self.sprite_grp.add(self.start_button)
            else:
                self.sprite_grp.add(self.buttonReady, self.buttonBack)

        self.sprite_grp.add(self.buttonBack)

        self._init_sprites()

    def _init_start_game_button(self):
        """Button for starting the game once all players have clicked ready."""
        box_size = (130, 48)
        self.start_button = RectButton(
            1050, 575, box_size[0], box_size[1], Color.GREY, 0,
            Text(pygame.font.SysFont('Agency FB', 25), "Start", Color.RED))
        self.start_button.change_bg_image(MEDIA_CONSTS.WOOD)
        self.start_button.add_frame(MEDIA_CONSTS.FRAME)
        self.sprite_grp.add(self.start_button)

    def _init_background(self):
        box_size = (self.resolution[0], self.resolution[1])
        background_box = RectLabel(0, 0, box_size[0], box_size[1],
                                   MEDIA_CONSTS.FLASHPOINT_BACKGROUND)
        self.sprite_grp.add(background_box)

    def create_butn_img(self, x, y, width, height, path):
        box_size = (width, height)
        self.this_img = RectButton(x, y, box_size[0], box_size[1], path)

        self.sprite_grp.add(self.this_img)

    def _init_background_player(self, rect):

        if not self._game.rules == GameKindEnum.FAMILY and self._current_player.role:
            role_path = self.get_path_from_character_enum(
                self._current_player.role)
            user_box = RectLabel(rect[0], rect[1], rect[2], rect[3], role_path)
        else:
            user_box = RectLabel(rect[0], rect[1], rect[2], rect[3],
                                 MEDIA_CONSTS.FAMILY)
        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

    def _init_text_box(self, position, text, color):
        box_size = (position[2], position[3])

        user_box = RectLabel(
            position[0], position[1], box_size[0], box_size[1], color, 0,
            Text(pygame.font.SysFont('Agency FB', 20), text, (0, 255, 0, 0)))
        return user_box

    def _init_selec_char(self, x_pos: int, y_pos: int, text: str, color: Color,
                         color_text: Color):
        box_size = (170, 48)
        self.buttonSelChar = RectButton(
            x_pos, y_pos, box_size[0], box_size[1], color, 0,
            Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonSelChar.change_bg_image(MEDIA_CONSTS.WOOD)
        self.buttonSelChar.add_frame(MEDIA_CONSTS.FRAME)
        self.sprite_grp.add(self.buttonSelChar)

    def _init_ready(self, x_pos: int, y_pos: int, text: str, color: Color,
                    color_text: Color):

        box_size = (130, 48)
        self.isReady = False
        self.buttonReady = RectButton(
            x_pos, y_pos, box_size[0], box_size[1], color, 0,
            Text(pygame.font.SysFont('Agency FB', 25), text, Color.GREY))
        self.buttonReady.change_bg_image(MEDIA_CONSTS.WOOD)
        self.buttonReady.add_frame(MEDIA_CONSTS.FRAME)
        self.sprite_grp.add(self.buttonReady)

    def _init_btn_back(self, x_pos: int, y_pos: int, text: str, bg: str,
                       color_text: Color):
        box_size = (130, 48)
        self.buttonBack = RectButton(
            x_pos, y_pos, box_size[0], box_size[1], bg, 0,
            Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonBack.add_frame(MEDIA_CONSTS.FRAME)
        self.sprite_grp.add(self.buttonBack)

    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)

    def _init_sprites(self):
        text_pos = [(565, 625, 200, 32), (100, 364, 150, 32),
                    (400, 289, 150, 32), (780, 289, 150, 32),
                    (1080, 364, 150, 32)]
        background_pos = [(565, 375, 200, 250), (100, 164, 150, 200),
                          (400, 89, 150, 200), (780, 89, 150, 200),
                          (1080, 164, 150, 200)]
        self.player_boxes = []
        current_player = [
            player for player in GameStateModel.instance().players
            if player.ip == self._current_player.ip
        ][0]
        self.player_boxes.append(
            PlayerBox(text_pos[0], background_pos[0],
                      self._current_player.nickname, current_player,
                      current_player.color))

        players = [
            x for x in GameStateModel.instance().players
            if x.ip != self._current_player.ip
        ]
        i = 1
        for player in players:
            self.player_boxes.append(
                PlayerBox(text_pos[i], background_pos[i], player.nickname,
                          player, player.color))
            # self.sprite_grp.add(self._init_text_box(text_pos[i], player.nickname, player.color))
            # self.sprite_grp.add(self._init_background_player(background_pos[i]))
            i += 1

    def not_enough_players_ready_prompt(self):
        """Prompt to the host that there are not enough players to join the game."""
        label_width = 400
        label_height = 30
        label_left = 1050 - 100
        label_top = (pygame.display.get_surface().get_size()[1] -
                     50) - (label_height / 2)
        message = f"Not all players are ready!"
        prompt_label = RectLabel(label_left,
                                 label_top,
                                 label_width,
                                 label_height,
                                 Color.WHITE,
                                 txt_obj=Text(
                                     pygame.font.SysFont('Agency FB', 24),
                                     message))
        prompt_label.set_transparent_background(True)
        self.players_not_ready_prompt = prompt_label

    def draw(self, screen):
        self.sprite_grp.draw(screen)

        for box in self.player_boxes:
            box.draw(screen)

        self.chat_box.draw(screen)

        if self.players_not_ready_prompt:
            self.players_not_ready_prompt.draw(screen)

    def update(self, event_queue):
        if Networking.get_instance().is_host:
            game = GameStateModel.instance()
            players_ready = len([
                player for player in game.players
                if player.status == PlayerStatusEnum.READY
            ])

            if players_ready == game.max_players:
                self.sprite_grp.remove(self.start_button)
                self.start_button = RectButton(
                    1050, 575, 130, 48, Color.RED, 0,
                    Text(pygame.font.SysFont('Agency FB', 25), "Start",
                         Color.GREEN))
                self.start_button.on_click(self.start_game)
                self.start_button.change_bg_image(MEDIA_CONSTS.WOOD)
                self.start_button.add_frame(MEDIA_CONSTS.FRAME)
                self.sprite_grp.add(self.start_button)

                # self.start_button.txt_obj.set_color(Color.GREEN)
            else:
                self.sprite_grp.remove(self.start_button)
                self.start_button = RectButton(
                    1050, 575, 130, 48, Color.GREEN, 0,
                    Text(pygame.font.SysFont('Agency FB', 25), "Start",
                         Color.RED))
                self.start_button.disable()
                self.start_button.change_bg_image(MEDIA_CONSTS.WOOD)
                self.start_button.add_frame(MEDIA_CONSTS.FRAME)
                self.sprite_grp.add(self.start_button)

        self.chat_box.update(event_queue)

        # game is mutated by reference, BE CAREFUL!!!
        if len(GameStateModel.instance().players) != self._player_count:
            self._player_count = len(GameStateModel.instance().players)
            self.sprite_grp.empty()
            self._init_all(reuse=True)

        self.sprite_grp.update(event_queue)

    def notify_player_index(self, player_index: int):
        pass

    def notify_game_state(self, game_state: GameStateEnum):
        pass

    def damage_changed(self, new_damage: int):
        pass

    def saved_victims(self, victims_saved: int):
        pass

    def dead_victims(self, victims_dead: int):
        pass

    def player_added(self, player: PlayerModel):
        pass

    def player_removed(self, player: PlayerModel):
        pass

    def player_command(self, source: PlayerModel, target: PlayerModel):
        pass
예제 #3
0
class TileSprite(Interactable, TileObserver):
    """Graphical representation of a Tile and controls."""
    def __init__(self, image: pygame.Surface, fire_image: pygame.Surface,
                 smoke_image: pygame.Surface, x, y, x_offset, y_offset, row,
                 column):
        self.index = 0
        self.sprite_grp = pygame.sprite.Group()
        self.image = image
        self._highlight_color = None
        self.row = row
        self.column = column

        self._fire_image = fire_image
        self._smoke_image = smoke_image
        self._non_highlight_image = image.copy()
        self._blank_image = image.copy()

        self.counter = 80

        self.explosion = False
        self.explosion_image = image.copy()
        self.explosion_image.blit(pygame.image.load(EXPLOSION),
                                  (0, 0, 128, 128))
        self.explosion_image.get_rect().move_ip(x_offset, y_offset)

        self.fire_deck_gun = False
        self.fire_deck_gun_image = image.copy()
        self.fire_deck_gun_image.blit(
            pygame.transform.scale(pygame.image.load(WATER), (128, 128)),
            (0, 0, 128, 128))
        self.fire_deck_gun_image.get_rect().move_ip(x_offset, y_offset)

        # Initialize if place is Fire, Smoke or Safe
        tile = GameStateModel.instance().game_board.get_tile_at(row, column)
        status = tile.space_status
        is_hotspot = tile.is_hotspot
        self.tile_status_changed(status, is_hotspot)

        Interactable.__init__(self, self.image.get_rect())
        self.rect = self.image.get_rect().move(x_offset, y_offset)
        self.mouse_rect = pygame.Rect(self.rect).move(x, y)
        self._is_hovered = False
        self._mouse_pos = (0, 0)  # For keeping track of previous location.
        self.is_scrolling = False

        # ------- POP-UP MENU -------- #
        self.identify_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Identify",
                 Color.GREEN2))
        pygame.draw.rect(self.identify_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.move_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Move Here",
                 Color.GREEN2))
        pygame.draw.rect(self.move_button.image, Color.YELLOW, [0, 0, 100, 25],
                         3)

        self.extinguish_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Extinguish",
                 Color.GREEN2))
        pygame.draw.rect(self.extinguish_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.pickup_victim_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Carry Victim",
                 Color.GREEN2))
        pygame.draw.rect(self.pickup_victim_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.drop_victim_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Leave Victim",
                 Color.GREEN2))
        pygame.draw.rect(self.drop_victim_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.lead_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Lead Victim",
                 Color.GREEN2))

        pygame.draw.rect(self.lead_button.image, Color.YELLOW, [0, 0, 100, 25],
                         3)

        self.change_crew_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Change Crew",
                 Color.GREEN2))
        pygame.draw.rect(self.change_crew_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.stop_lead_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Leave Victim",
                 Color.GREEN2))

        pygame.draw.rect(self.stop_lead_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.drive_ambulance_here_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Drive Ambulance Here",
                 Color.GREEN2))

        pygame.draw.rect(self.drive_ambulance_here_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.drive_engine_here_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Drive Engine Here",
                 Color.GREEN2))

        pygame.draw.rect(self.drive_engine_here_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.ride_vehicle_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Ride Vehicle",
                 Color.GREEN2))

        pygame.draw.rect(self.ride_vehicle_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.remove_hazmat_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Remove Hazmat",
                 Color.GREEN2))

        pygame.draw.rect(self.remove_hazmat_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.dismount_vehicle_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Dismount Vehicle",
                 Color.GREEN2))

        pygame.draw.rect(self.dismount_vehicle_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.fire_deck_gun_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Fire Deck Gun",
                 Color.GREEN2))

        pygame.draw.rect(self.fire_deck_gun_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.resuscitate_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Resuscitate",
                 Color.GREEN2))

        pygame.draw.rect(self.resuscitate_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.command_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Command",
                 Color.GREEN2))

        pygame.draw.rect(self.command_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.pickup_hazmat_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Pickup Hazmat",
                 Color.GREEN2))

        pygame.draw.rect(self.pickup_hazmat_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.drop_hazmat_button = RectButton(
            self.rect.x, self.rect.y, 100, 25, Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 15), "Drop Hazmat",
                 Color.GREEN2))

        pygame.draw.rect(self.drop_hazmat_button.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)

        self.disable_all()

    def __str__(self):
        return f"TileSprite at: {self.row},{self.column}"

    def _draw_hightlight(self):
        self.image.blit(self._non_highlight_image, (0, 0))
        hover = pygame.Surface(
            (self._non_highlight_image.get_width(),
             self._non_highlight_image.get_height())).convert_alpha()
        if self._highlight_color:
            hover.fill(self._highlight_color)
            hover.set_alpha(10)
            self.image.blit(hover, (0, 0),
                            special_flags=pygame.BLEND_RGBA_MULT)

    @property
    def highlight_color(self):
        return self._highlight_color

    @highlight_color.setter
    def highlight_color(self, color: Tuple[int, int, int]):
        self._highlight_color = color

    def hover(self):
        if self._is_enabled:
            mouse = pygame.mouse.get_pos()
            rect = self.rect
            x_max = rect.x + rect.w
            x_min = rect.x
            y_max = rect.y + rect.h
            y_min = rect.y
            return x_max > mouse[0] > x_min and y_max > mouse[1] > y_min
        else:
            return False

    def disable_all(self):
        # Disable all buttons
        self.identify_button.disable()
        self.move_button.disable()
        self.extinguish_button.disable()
        self.pickup_victim_button.disable()
        self.drop_victim_button.disable()
        self.drive_ambulance_here_button.disable()
        self.drive_engine_here_button.disable()
        self.ride_vehicle_button.disable()
        self.dismount_vehicle_button.disable()
        self.command_button.disable()
        self.remove_hazmat_button.disable()
        self.pickup_hazmat_button.disable()
        self.drop_hazmat_button.disable()
        self.resuscitate_button.disable()
        self.lead_button.disable()
        self.stop_lead_button.disable()
        self.fire_deck_gun_button.disable()
        self.change_crew_button.disable()

        # Important! Reset the on_clicks
        self.identify_button.on_click(None)
        self.move_button.on_click(None)
        self.extinguish_button.on_click(None)
        self.pickup_victim_button.on_click(None)
        self.drop_victim_button.on_click(None)
        self.drive_ambulance_here_button.on_click(None)
        self.drive_engine_here_button.on_click(None)
        self.ride_vehicle_button.on_click(None)
        self.dismount_vehicle_button.on_click(None)
        self.command_button.on_click(None)
        self.remove_hazmat_button.on_click(None)
        self.pickup_hazmat_button.on_click(None)
        self.drop_hazmat_button.on_click(None)
        self.resuscitate_button.on_click(None)
        self.lead_button.on_click(None)
        self.stop_lead_button.on_click(None)
        self.fire_deck_gun_button.on_click(None)
        self.change_crew_button.on_click(None)

    def is_clicked(self):
        if not self.hover():
            return False

        for event in EventQueue.get_instance():
            if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                return True
        return False

    def enable(self):
        """
        Enables the event hook
        :return:
        """
        self._is_enabled = True

    def disable(self):
        """
        Disables the event hook
        :return:
        """
        self._is_enabled = False

    def _scroll(self):
        """Move this Sprite in the direction of the scroll."""
        current_mouse_pos = pygame.mouse.get_pos()
        pressed = pygame.mouse.get_pressed()[2]  # right click
        movement = (current_mouse_pos[0] - self._mouse_pos[0],
                    current_mouse_pos[1] - self._mouse_pos[1])
        if pressed:
            grid = self.groups()[0]
            if (grid.rect.left < current_mouse_pos[0] < grid.rect.right and
                    grid.rect.top < current_mouse_pos[1] < grid.rect.bottom):
                self.rect.move_ip(movement)
                self.mouse_rect.move_ip(movement)
        self._mouse_pos = current_mouse_pos

    def draw(self, screen: pygame.Surface):

        if self.explosion:
            screen.blit(self.explosion_image, self.rect)
            self.counter -= 1
            if self.counter == 0:
                self.explosion = False
                self.counter = 80
                screen.blit(self.image, self.rect)
        elif self.fire_deck_gun:
            screen.blit(self.fire_deck_gun_image, self.rect)
            self.counter -= 1
            if self.counter == 0:
                self.fire_deck_gun = False
                self.counter = 80
                screen.blit(self.image, self.rect)

        else:
            self._draw_hightlight()
            screen.blit(self.image, self.rect)

    def draw_menu(self, screen: pygame.Surface):
        offset = 0
        inc = 30
        if self.move_button.enabled:
            self.draw_btn(self.move_button, offset, screen)
            offset += inc

        if self.extinguish_button.enabled:
            self.draw_btn(self.extinguish_button, offset, screen)
            offset += inc

        if self.pickup_victim_button.enabled:
            self.draw_btn(self.pickup_victim_button, offset, screen)
            offset += inc
        elif self.drop_victim_button.enabled:
            self.draw_btn(self.drop_victim_button, offset, screen)
            offset += inc

        if self.drive_ambulance_here_button.enabled:
            self.draw_btn(self.drive_ambulance_here_button, offset, screen)
            offset += inc

        if self.drive_engine_here_button.enabled:
            self.draw_btn(self.drive_engine_here_button, offset, screen)
            offset += inc

        if self.identify_button.enabled:
            self.draw_btn(self.identify_button, offset, screen)
            offset += inc

        if self.ride_vehicle_button.enabled:
            self.draw_btn(self.ride_vehicle_button, offset, screen)
            offset += inc

        if self.dismount_vehicle_button.enabled:
            self.draw_btn(self.dismount_vehicle_button, offset, screen)
            offset += inc

        if self.remove_hazmat_button.enabled:
            self.draw_btn(self.remove_hazmat_button, offset, screen)
            offset += inc

        if self.pickup_hazmat_button.enabled:
            self.draw_btn(self.pickup_hazmat_button, offset, screen)
            offset += inc

        elif self.drop_hazmat_button.enabled:
            self.draw_btn(self.drop_hazmat_button, offset, screen)
            offset += inc

        if self.resuscitate_button.enabled:
            self.draw_btn(self.resuscitate_button, offset, screen)
            offset += inc

        if self.fire_deck_gun_button.enabled:
            screen.blit(self.fire_deck_gun_button.image,
                        self.fire_deck_gun_button.rect)
            self.fire_deck_gun_button.rect.x = self.rect.x
            self.fire_deck_gun_button.rect.y = self.rect.y + offset
            offset += inc

        if self.change_crew_button.enabled:
            screen.blit(self.change_crew_button.image,
                        self.change_crew_button.rect)
            self.change_crew_button.rect.x = self.rect.x
            self.change_crew_button.rect.y = self.rect.y + offset
            offset += inc

        if self.command_button.enabled:
            self.draw_btn(self.command_button, offset, screen)
            offset += inc

        if self.lead_button.enabled:
            self.draw_btn(self.lead_button, offset, screen)
            offset += inc

        if self.stop_lead_button.enabled:
            self.draw_btn(self.stop_lead_button, offset, screen)
            offset += inc

    def draw_btn(self, button: RectButton, offset: int,
                 screen: pygame.Surface):
        screen.blit(button.image, button.rect)
        button.rect.x = self.rect.x
        button.rect.y = self.rect.y + offset

    def update(self, event_queue: EventQueue):
        self.sprite_grp.update(event_queue)

        self.drive_ambulance_here_button.update(event_queue)
        self.drop_victim_button.update(event_queue)
        self.extinguish_button.update(event_queue)
        self.pickup_victim_button.update(event_queue)
        self.move_button.update(event_queue)
        self.identify_button.update(event_queue)
        self.ride_vehicle_button.update(event_queue)
        self.dismount_vehicle_button.update(event_queue)
        self.drive_engine_here_button.update(event_queue)
        self.command_button.update(event_queue)
        self.remove_hazmat_button.update(event_queue)
        self.drop_hazmat_button.update(event_queue)
        self.pickup_hazmat_button.update(event_queue)
        self.resuscitate_button.update(event_queue)
        self.fire_deck_gun_button.update(event_queue)
        self.lead_button.update(event_queue)
        self.stop_lead_button.update(event_queue)
        self.change_crew_button.update(event_queue)

        self._scroll()
        if self.is_clicked():
            self.click()

    def tile_status_changed(self, status: SpaceStatusEnum, is_hotspot: bool):
        new_surf = pygame.Surface([
            self._non_highlight_image.get_width(),
            self._non_highlight_image.get_height()
        ])
        self._non_highlight_image = self._blank_image.copy()

        new_surf = pygame.Surface.convert_alpha(new_surf)
        new_surf.fill((0, 0, 0, 0), None, pygame.BLEND_RGBA_MULT)

        if status == SpaceStatusEnum.FIRE:
            image_file = FileImporter.import_image(
                "media/All Markers/fire.png")
            new_surf.blit(image_file, (0, 0))
        elif status == SpaceStatusEnum.SMOKE:
            image_file = FileImporter.import_image(
                "media/All Markers/smoke.png")
            new_surf.blit(image_file, (0, 0))

        if is_hotspot:
            hs_img = FileImporter.import_image(
                "media/all_markers/hot_spot.png")
            new_surf.blit(hs_img, (0, 0))

        self._non_highlight_image.blit(new_surf, (0, 0))

    def tile_assoc_models_changed(self, assoc_models: List[Model]):
        pass
예제 #4
0
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)
예제 #5
0
class WallSprite(pygame.sprite.Sprite, WallObserver):
    def __init__(self, wall_model: WallModel, orientation: str,
                 tile_sprite: TileSprite, tile_model: TileModel,
                 id: Tuple[int, int, str]):
        super().__init__()
        self.orientation = orientation
        self._game: GameStateModel = GameStateModel.instance()
        self._current_player = self._game.players_turn
        self._button = None
        self.tile_model = tile_model
        self.id = id
        self.wall_model = wall_model
        self.wall_model.add_observer(self)

        self.damaged = self.wall_model.wall_status == WallStatusEnum.DAMAGED
        self.destroyed = self.wall_model.wall_status == WallStatusEnum.DESTROYED
        self.tile_sprite = tile_sprite
        self._prev_x = self.tile_sprite.rect.x
        self._prev_y = self.tile_sprite.rect.y
        self.button_input = RectButton(
            self.tile_sprite.rect.x, self.tile_sprite.rect.y, 100, 25,
            Color.WOOD, 0,
            Text(pygame.font.SysFont('Agency FB', 20), "Chop Wall",
                 Color.GREEN2))
        pygame.draw.rect(self.button_input.image, Color.YELLOW,
                         [0, 0, 100, 25], 3)
        self.button_input.disable()
        self.can_chop = False

    @property
    def direction(self) -> str:
        return self.id[2]

    @property
    def wall(self):
        return self.wall_model

    @property
    def player(self) -> PlayerModel:
        return self._current_player

    @property
    def button(self):
        return self._button

    @button.setter
    def button(self, button):
        self._button = button

    def update(self, event_queue):
        diff_x = self.tile_sprite.rect.x - self._prev_x
        diff_y = self.tile_sprite.rect.y - self._prev_y
        self._button.rect.move_ip((diff_x, diff_y))
        self._prev_x = self.tile_sprite.rect.x
        self._prev_y = self.tile_sprite.rect.y
        self.button_input.rect.x = self.tile_sprite.rect.x + 14
        self.button_input.rect.y = self.tile_sprite.rect.y + 50

        for event in event_queue:
            if event.type == pygame.MOUSEBUTTONUP:
                if not ((self.button_input.rect.x <= pygame.mouse.get_pos()[0]
                         <= self.button_input.rect.x + 100) and
                        (self.button_input.rect.y <= pygame.mouse.get_pos()[1]
                         <= self.button_input.rect.y + 25)):
                    self.button_input.disable()
                    self.can_chop = False

        self._button.update(event_queue)
        self.button_input.update(event_queue)

    def wall_status_changed(self, status: WallStatusEnum):
        if status == WallStatusEnum.DAMAGED:
            self.damaged = True
        elif status == WallStatusEnum.DESTROYED:
            self.damaged = False
            self.destroyed = True

    def draw_menu(self, screen):
        self.button.draw(screen)
        if self.can_chop:
            self.button_input.draw(screen)

    def draw(self, screen):
        x_offset1 = 0 if self.orientation == "vertical" else 25
        y_offset1 = 0 if self.orientation == "horizontal" else 25
        x_offset2 = 0 if self.orientation == "vertical" else 50
        y_offset2 = 0 if self.orientation == "horizontal" else 50

        if self.damaged:
            marker = RectLabel(self.button.rect.x + x_offset1,
                               self.button.rect.y + y_offset1, 28, 28,
                               "media/Threat_Markers/damageMarker.png")
            marker.draw(screen)
        elif self.destroyed:
            marker = RectLabel(self.button.rect.x + x_offset2,
                               self.button.rect.y + y_offset2, 28, 28,
                               "media/Threat_Markers/damageMarker.png")
            marker.draw(screen)
            marker = RectLabel(self.button.rect.x + x_offset1,
                               self.button.rect.y + y_offset1, 28, 28,
                               "media/Threat_Markers/damageMarker.png")
            marker.draw(screen)

    def disable_chop(self):
        self.can_chop = False

    def enable_chop(self):
        self.can_chop = True