Beispiel #1
0
 def _init_continue_btn(self):
     box_size = (200, 50)
     ctn_btn = RectButton(
         550, 500, box_size[0], box_size[1], WOOD, 0,
         Text(pygame.font.SysFont('Agency FB', 20), "Continue",
              Color.GREEN2))
     ctn_btn.add_frame(FRAME)
     ctn_btn.on_click(self._continue)
     self.sprite_grp.add(ctn_btn)
 def _init_btn_back(self, x_pos: int, y_pos: int, text: str, color: color,
                    color_text: color):
     box_size = (130, 48)
     button_back = RectButton(
         x_pos, y_pos, box_size[0], box_size[1], color, 0,
         Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
     button_back.on_click(EventQueue.post,
                          CustomEvent(ChangeSceneEnum.HOSTMENUSCENE))
     button_back.change_bg_image(WOOD)
     button_back.add_frame(FRAME)
     self.sprite_grp.add(button_back)
 def _init_end_turn_button(self):
     btn = RectButton(1130,
                      500,
                      150,
                      50,
                      background=Color.ORANGE,
                      txt_obj=Text(pygame.font.SysFont('Arial', 23),
                                   "END TURN", Color.GREEN2))
     btn.change_bg_image(WOOD)
     btn.add_frame(FRAME)
     btn.on_click(self._end_turn)
     return btn
class HostJoinScene(Scene):
    def __init__(self, screen: pygame.Surface, current_player: PlayerModel):
        Scene.__init__(self, screen)
        self._current_player = current_player
        self._init_background()
        self._init_btn_host(575, 481, "Host", Color.STANDARDBTN, Color.GREEN2)
        self._init_btn_join(575, 371, "Join", Color.STANDARDBTN, Color.GREEN2)
        self._init_btn_back(20, 20, "Back", Color.STANDARDBTN, Color.GREEN2)
        self.buttonJoin.on_click(EventQueue.post,
                                 CustomEvent(ChangeSceneEnum.JOINSCENE))
        self.buttonBack.on_click(EventQueue.post,
                                 CustomEvent(ChangeSceneEnum.STARTSCENE))
        self.buttonHost.on_click(EventQueue.post,
                                 CustomEvent(ChangeSceneEnum.HOSTMENUSCENE))

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

    def _init_log_box(self):
        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],
                            Color.GREEN)
        self.sprite_grp.add(log_box)

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

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

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

        self.sprite_grp.add(self.buttonBack)
Beispiel #5
0
class JoinScene(object):
    def __init__(self, screen, current_player: PlayerModel):
        self._current_player = current_player
        self.resolution = (1280, 700)
        self.sprite_grp = pygame.sprite.Group()
        self._init_background()
        self._init_text_box(342, 350, "Enter IP:", Color.STANDARDBTN, Color.GREEN2)
        self._init_text_bar(500, 350, 400, 32)
        self._init_btn(625, 536, "Connect", Color.STANDARDBTN, Color.GREEN2)
        self._init_btn_back(20, 20, "Back", Color.STANDARDBTN, Color.GREEN2)
        self._text_bar = self._init_text_bar(500, 350, 400, 32)
        self.error_msg = ""
        self.buttonBack.on_click(EventQueue.post, CustomEvent(ChangeSceneEnum.HOSTJOINSCENE, player=self._current_player))
        self.buttonConnect.on_click(self.join)

    def join(self):
        """
        Start the join host process in Networking
        :param ip_addr: ip address to connect
        :param next_scene: next scene to be called after the process completes
        :param args: extra arguments for the next scene
        :return:
        """

        ip_addr = self.text_bar_msg

        try:
            self._current_player.status = PlayerStatusEnum.NOT_READY
            Networking.get_instance().join_host(ip_addr, player=self._current_player)
            reply = Networking.wait_for_reply()
            # Connection error will be raised if no reply
            if reply:
                reply = JSONSerializer.deserialize(reply)
                if isinstance(reply, TooManyPlayersEvent):
                    raise TooManyPlayersException(self._current_player)
                # GameStateModel.set_game(JSONSerializer.deserialize(reply))
                EventQueue.post(CustomEvent(ChangeSceneEnum.LOBBYSCENE))
        except TimeoutError:
            msg = "Host not found."
            print(msg)
            self.init_error_message(msg)
        except TooManyPlayersException:
            msg = "Lobby is full. Cannot join the game."
            print(msg)
            self.init_error_message(msg)
            # Disconnect client that's trying to connect
            if not Networking.get_instance().is_host:
                Networking.get_instance().client.disconnect()
        except Networking.Client.SocketError:
            msg = "Failed to establish connection."
            print(msg)
            self.init_error_message(msg)
        except OSError:
            msg = "Invalid IP address"
            print(msg)
            self.init_error_message(msg)

    def _init_text_box(self, x_pos, y_pos, text, color: Color, color_text: Color):
        box_size = (136, 32)

        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_background(self):
        box_size = (self.resolution[0], self.resolution[1])
        background_box = RectLabel(0, 0, box_size[0], box_size[1], FLASHPOINT_BACKGROUND)
        self.sprite_grp.add(background_box)

    def _init_btn(self, x_pos, y_pos, text, color: Color, color_text: Color):
        box_size = (130, 48)
        self.buttonConnect = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                        Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonConnect.change_bg_image(WOOD)
        self.buttonConnect.add_frame(FRAME)
        self.sprite_grp.add(self.buttonConnect)

    def _init_text_bar(self, x_pos, y_pos, width, height):
        inputbox = InputBox(x=x_pos, y=y_pos, w=width, h=height)
        inputbox.disable_enter()
        return inputbox

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

    def init_error_message(self, msg):
        label_width = 400
        label_left = (pygame.display.get_surface().get_size()[0] / 2) - (label_width / 2)
        label_top = (pygame.display.get_surface().get_size()[1] / 6) * 2
        error_msg_label = RectLabel(label_left, label_top, label_width, label_width, (255, 255, 255),
                                    txt_obj=(Text(pygame.font.SysFont('Agency FB', 24), msg, Color.RED)))
        error_msg_label.set_transparent_background(True)
        self.error_msg = error_msg_label

    def draw(self, screen):
        self.sprite_grp.draw(screen)
        self._text_bar.draw(screen)
        if self.error_msg:
            self.error_msg.draw(screen)

    def update(self, event_queue):
        self.sprite_grp.update(event_queue)
        self._text_bar.update(event_queue)
        if self.error_msg:
            self.error_msg.update(event_queue)

    @property
    def text_bar_msg(self):
        return self._text_bar.text
class CreateGameMenuScene(Scene):
    def __init__(self, screen: pygame.Surface, current_player: PlayerModel):
        Scene.__init__(self, screen)
        self._current_player = current_player

        self._init_background()
        self._init_text_box(344, 387, 200, 32, "Regular Mode:", Color.STANDARDBTN, Color.GREEN2)
        self._init_text_box(344, 506, 200, 32, "Advanced Modes:", Color.STANDARDBTN, Color.GREEN2)
        self._init_btn_back(20, 20, "Back", Color.STANDARDBTN, Color.GREEN2)
        self._init_btn_family(575, 381, "Family", Color.STANDARDBTN, Color.GREEN2)
        self._init_btn_rec(575, 500, "Recruit", Color.GREEN, Color.GREEN)
        self._init_btn_veteran(710, 500, "Veteran", Color.YELLOW, Color.YELLOW)
        self._init_btn_heroic(845, 500, "Heroic", Color.RED, Color.RED)

        self.buttonRecruit.on_click(self.create_new_game, GameKindEnum.EXPERIENCED, DifficultyLevelEnum.RECRUIT)
        self.buttonVeteran.on_click(self.create_new_game, GameKindEnum.EXPERIENCED, DifficultyLevelEnum.VETERAN)
        self.buttonHeroic.on_click(self.create_new_game, GameKindEnum.EXPERIENCED, DifficultyLevelEnum.HEROIC)
        self.buttonFamily.on_click(self.create_new_game, GameKindEnum.FAMILY)
        self.buttonBack.on_click(self._disconnect_and_back)

    @staticmethod
    def _disconnect_and_back():
        Networking.get_instance().disconnect()
        EventQueue.post(CustomEvent(ChangeSceneEnum.HOSTMENUSCENE))

    # ------------- GAME CREATE/LOAD STUFF ---------- #

    def create_new_game(self, game_kind: GameKindEnum, difficulty_level: DifficultyLevelEnum = None):
        """Instantiate a new family game and move to the lobby scene."""
        GameStateModel(self._current_player, 6, game_kind, GameBoardTypeEnum.ORIGINAL, difficulty_level)
        EventQueue.post(CustomEvent(ChangeSceneEnum.CHOOSEBOARDSCENE))

    # ----------------------------------------------- #

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

    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_btn_family(self, x_pos: int, y_pos: int, text: str, color: Color, color_text: Color):
        box_size = (130, 48)
        self.buttonFamily = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                       Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonFamily.change_bg_image(WOOD)
        pygame.draw.rect(self.buttonFamily.image, Color.GREEN2, [0, 0, box_size[0], box_size[1]], 7)
        self.sprite_grp.add(self.buttonFamily)

    def _init_btn_rec(self, x_pos: int, y_pos: int, text: str, color: Color, color_text: Color):
        box_size = (130, 48)
        self.buttonRecruit = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                    Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonRecruit.change_bg_image(WOOD)
        pygame.draw.rect(self.buttonRecruit.image, Color.GREEN, [0, 0, box_size[0], box_size[1]], 7)
        self.sprite_grp.add(self.buttonRecruit)

    def _init_btn_veteran(self, x_pos: int, y_pos: int, text: str, color: Color, color_text: Color):
        box_size = (130, 48)
        self.buttonVeteran = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                    Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonVeteran.change_bg_image(WOOD)
        pygame.draw.rect(self.buttonVeteran.image, Color.YELLOW, [0, 0, box_size[0], box_size[1]], 7)
        self.sprite_grp.add(self.buttonVeteran)

    def _init_btn_heroic(self, x_pos: int, y_pos: int, text: str, color: Color, color_text: Color):
        box_size = (130, 48)
        self.buttonHeroic = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                    Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonHeroic.change_bg_image(WOOD)
        pygame.draw.rect(self.buttonHeroic.image, Color.RED, [0, 0, box_size[0], box_size[1]], 7)
        self.sprite_grp.add(self.buttonHeroic)

    def _init_btn_back(self, x_pos: int, y_pos: int, text: str, color: Color, color_text: Color):
        box_size = (130, 48)
        self.buttonBack = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                     Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonBack.change_bg_image(WOOD)
        self.buttonBack.add_frame(FRAME)
        self.sprite_grp.add(self.buttonBack)
Beispiel #7
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
Beispiel #8
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)
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)
Beispiel #11
0
class StartScene(object):
    def __init__(self, screen):
        self.profiles = PROFILES
        self.resolution = (1280, 700)
        self.sprite_grp = pygame.sprite.Group()
        self._init_background()

        self._init_profile_selector(((self.resolution[0]/2)-(500/2)), 330, color.GREY)
        self.text_bar1 = self._init_text_bar(((self.resolution[0]/2)-(500/2))-20, 600, 400, 32)
        self.text_bar1.disable_enter()

        self._init_btn_register(((self.resolution[0]/2)-(500/2))+400, 592, "Create Profile",
                                color.STANDARDBTN, color.GREEN2)
        self.update_profiles()

    def _init_background(self):
        box_size = (self.resolution[0], self.resolution[1])
        background_box = RectLabel(0, 0, box_size[0], box_size[1], FLASHPOINT_BACKGROUND)
        self.sprite_grp.add(background_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_text_box(self, x_pos, y_pos, text, clr, color_text):
        box_size = (136, 32)

        user_box = RectLabel(x_pos, y_pos, box_size[0], box_size[1], clr, 0,
                             Text(pygame.font.SysFont('Agency FB', 20), text, color_text))
        self.sprite_grp.add(user_box)

    def _init_btn_register(self, x_pos, y_pos, text, clr, color_text):
        box_size = (130, 48)
        self.buttonRegister = RectButton(x_pos, y_pos, box_size[0], box_size[1], clr, 0,
                                         Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonRegister.change_bg_image(WOOD)
        self.buttonRegister.add_frame(FRAME)
        self.buttonRegister.on_click(self.register_profile)
        self.sprite_grp.add(self.buttonRegister)

    def register_profile(self):
        # Gets the text in the text bar and send the create profile event to the event queue (scene manager)
        self.create_profile(self.text_bar1)
        self.update_profiles()

    @staticmethod
    def _init_text_bar(x_pos, y_pos, width, height):
        return InputBox(x=x_pos, y=y_pos, w=width, h=height)

    def _init_profile_selector(self, x_pos, y_pos, clr):
        box_size = (500, 250)
        self.profile = ProfileList(x_pos, y_pos, box_size[0], box_size[1], 3, clr)

    def draw(self, screen):
        self.sprite_grp.draw(screen)
        # self._text_bar2.draw(screen)
        self.text_bar1.draw(screen)
        self.profile.draw(screen)

    def update(self, event_queue):
        self.sprite_grp.update(event_queue)
        self.text_bar1.update(event_queue)
        self.profile.update(event_queue)
        # self._text_bar2.update(event_queue)

    def init_error_message(self, msg):
        label_width = 400
        label_left = (pygame.display.get_surface().get_size()[0] / 2) - (label_width / 2)
        label_top = (pygame.display.get_surface().get_size()[1] / 6) * 2
        error_msg_label = RectLabel(label_left, label_top, label_width, label_width, (255, 255, 255),
                                    txt_obj=(Text(pygame.font.SysFont('Agency FB', 24), msg, color.RED)))
        error_msg_label.set_transparent_background(True)
        self.error_msg = error_msg_label

# ------------ Stuff for profiles and start scene ------------ #

    def update_profiles(self):
        if not os.path.exists(self.profiles):
            with open(self.profiles, mode="w+", encoding='utf-8') as myFile:
                myFile.write("[]")
        with open(self.profiles, mode='r', encoding='utf-8') as myFile:
            temp = json.load(myFile)
            for i, user in enumerate(temp):
                player: PlayerModel = JSONSerializer.deserialize(user)
                player.ip = Networking.get_instance().get_ip()
                player.set_pos(-1, -1)
                player.ap = 0
                player.special_ap = 0
                player.carrying_victim = NullModel()
                self.profile.set_profile(
                    i, player.nickname, player.wins, player.losses, EventQueue.post,
                    CustomEvent(ChangeSceneEnum.HOSTJOINSCENE, player=player)
                )
                self.profile.remove_profile_callback(i, self.remove_profile, player.nickname)

    def create_profile(self, text_bar: InputBox):
        temp = {}
        with open(self.profiles, mode='r+', encoding='utf-8') as myFile:

            temp = json.load(myFile)
            size = len(temp)
            if size >= 3:
                return

            if not text_bar.text.strip():
                return

            size = len(text_bar.text.strip())

            if size <= 12:
                player_model = PlayerModel(
                    ip=Networking.get_instance().get_ip(),
                    nickname=text_bar.text.strip()
                )
                player = JSONSerializer.serialize(player_model)
                temp.append(player)
            else:
                msg = "Nickname must have less than 12 letters"
                self.init_error_message(msg)

        with open(self.profiles, mode='w', encoding='utf-8') as myFile:
            json.dump(temp, myFile)

        self.update_profiles()

    def remove_profile(self, removename: str):
        temp = {}
        with open(self.profiles, mode='r+', encoding='utf-8') as myFile:
            temp = json.load(myFile)
            for perm in temp:
                for name in perm.values():
                    if name == removename:
                        temp.remove(perm)
                    else:
                        continue

        with open(self.profiles, mode='w', encoding='utf-8') as myFile:
            json.dump(temp, myFile)

        self.update_profiles()
Beispiel #12
0
class CharacterScene(Scene):
    def __init__(self, screen, current_player: PlayerModel):
        self.label_grp = pygame.sprite.Group()
        self._current_player = current_player
        Scene.__init__(self, screen)
        self._init_background()
        self._game = GameStateModel.instance()

        self.create_label(0, 0, 100, 150, 1)
        self.create_butn_img(150, 150, 99, 150,
                             MEDIA_CONSTS.CAFS_FIREFIGHTER, 1)

        self.create_butn_img(350, 150, 100, 150,
                             MEDIA_CONSTS.DRIVER_OPERATOR, 2)

        self.create_butn_img(550, 150, 100, 150,
                             MEDIA_CONSTS.FIRE_CAPTAIN, 3)

        self.create_butn_img(750, 150, 99, 150,
                             MEDIA_CONSTS.GENERALIST, 4)

        self.create_butn_img(150, 450, 100, 150,
                             MEDIA_CONSTS.HAZMAT_TECHNICIAN, 5)

        self.create_butn_img(350, 450, 99, 150,
                             MEDIA_CONSTS.IMAGING_TECHNICIAN, 6)

        self.create_butn_img(550, 450, 99, 150,
                             MEDIA_CONSTS.PARAMEDIC, 7)

        self.create_butn_img(750, 450, 98, 150,
                             MEDIA_CONSTS.RESCUE_SPECIALIST, 8)

        self.create_butn_img(950, 150, 98, 150,
                             MEDIA_CONSTS.DOGE, 9)

        self.create_butn_img(950, 450, 99, 150,
                             MEDIA_CONSTS.VETERAN, 10)

        self._init_btn_back(20, 20, "Back", Color.STANDARDBTN, Color.BLACK)

        self._init_btn_confirm(1100, 575, "Confirm", Color.STANDARDBTN, Color.BLACK)

        self._init_title_text()
        self.character_enum: PlayerRoleEnum = None
        self.buttonBack.on_click(EventQueue.post, CustomEvent(ChangeSceneEnum.LOBBYSCENE))
        self.buttonConfirm.on_click(self.confirm)

    def confirm(self):
        if self.character_enum:

            accept = True  # This is a boolean flag

            if any([player.role == self.character_enum for player in self._game.players]):
                accept = False

            if accept:  # means no one took this character
                EventQueue.post(CustomEvent(ChangeSceneEnum.LOBBYSCENE))

                event = ChooseCharacterEvent(self.character_enum, self._game.players.index(self._current_player))

                if Networking.get_instance().is_host:
                    Networking.get_instance().send_to_all_client(event)
                else:
                    Networking.get_instance().send_to_server(event)

    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: str, count: int):
        label = self.create_label(x, y, width, height, count)
        self.label_grp.add(label)
        self.sprite_grp.add(label)

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

        role: PlayerRoleEnum = self.decide_enum(count)

        self.this_img.on_click(self.click_img, label, role)

        self.sprite_grp.add(self.this_img)

    @staticmethod
    def decide_enum(count: int):
        if count == 1:
            return PlayerRoleEnum.CAFS

        elif count == 2:
            return PlayerRoleEnum.DRIVER

        elif count == 3:
            return PlayerRoleEnum.CAPTAIN

        elif count == 4:
            return PlayerRoleEnum.GENERALIST

        elif count == 5:
            return PlayerRoleEnum.HAZMAT

        elif count == 6:
            return PlayerRoleEnum.IMAGING

        elif count == 7:
            return PlayerRoleEnum.PARAMEDIC

        elif count == 8:
            return PlayerRoleEnum.RESCUE

        elif count == 9:
            return PlayerRoleEnum.DOGE

        elif count == 10:
            return PlayerRoleEnum.VETERAN

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

    def _init_title_text(self):
        box_size = (400, 50)
        self.text_title = RectButton(400, 60, box_size[0], box_size[1], Color.BLACK, 0,
                                     Text(pygame.font.SysFont('Agency FB', 35), "Character Selection", Color.GREEN2))
        self.text_title.change_bg_image(MEDIA_CONSTS.WOOD)
        self.text_title.add_frame(MEDIA_CONSTS.FRAME)
        self.sprite_grp.add(self.text_title)

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

    def create_label(self, x_pos: int, y_pos: int, width: int, height: int, count: int):

        role: PlayerRoleEnum = self.decide_enum(count)

        accept = True

        if any([player.role == role for player in self._game.players]):
            accept = False

        if not accept:
            label =  RectLabel(x_pos - 15, y_pos - 15, width + 30, height + 30, Color.RED)
            label.change_bg_image(MEDIA_CONSTS.WOOD)
            return label
        else:
            label =  RectLabel(x_pos - 15, y_pos - 15, width + 30, height + 30, Color.GREEN)
            label.change_bg_image(MEDIA_CONSTS.WOOD)
            return label

    def set_color(self, sprite: pygame.sprite.Sprite, i: int=0, enum:PlayerRoleEnum=None):
        accept = True
        role = self.decide_enum(i) if i else enum
        if any([player.role == role for player in self._game.players]):
            accept = False
        if isinstance(sprite, RectLabel):
            if accept:
                #sprite.change_color(Color.GREEN)
                pygame.draw.rect(sprite.image, Color.GREEN, [0, 0, 130, 180], 7)
            else:
                #sprite.change_color(Color.RED)
                pygame.draw.rect(sprite.image, Color.RED, [0, 0, 130, 180], 7)
            if self.character_enum == role:
                #sprite.change_color(Color.WHITE)
                pygame.draw.rect(sprite.image, Color.WHITE, [0, 0, 130, 180], 7)

    def click_img(self, btn, enum: PlayerRoleEnum):
        self.character_enum = enum
        self.set_color(btn, enum=enum)

    def update(self, event_queue: EventQueue):
        for i, sprite in enumerate(self.label_grp, 1):
            self.set_color(sprite, i)
        self.sprite_grp.update(event_queue)
Beispiel #13
0
class ChooseBoardScene(object):
    def __init__(self, screen, current_player: PlayerModel):
        self.game_kind = GameStateModel.instance().rules
        self.sprite_grp = pygame.sprite.Group()
        self._current_player = current_player
        self.resolution = (1280, 700)

        self._init_background()
        self._init_title_text()

        self._init_board1(410, 400, "Original", Color.STANDARDBTN,
                          Color.GREEN2)
        self._init_board2(575, 400, "Alternative", Color.STANDARDBTN,
                          Color.GREEN2)
        self._init_board3(740, 400, "Random", Color.STANDARDBTN, Color.GREEN2)
        self._init_btn_back(20, 20, "Back", Color.STANDARDBTN, Color.GREEN2)

    def _init_back_box(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))

        self.sprite_grp.add(user_box)

    def _init_title_text(self):
        box_size = (500, 50)
        self.text_title = RectButton((int)(1280 / 2 - 250), 300, box_size[0],
                                     box_size[1], Color.BLACK, 0,
                                     Text(pygame.font.SysFont('Agency FB', 35),
                                          "Choose Board", Color.GREEN2))
        self.text_title.change_bg_image(WOOD)
        self.text_title.add_frame(FRAME)
        self.sprite_grp.add(self.text_title)

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

    def _init_board1(self, x_pos: int, y_pos: int, text: str, color: Color,
                     color_text: Color):
        box_size = (130, 48)
        self.button_board1 = RectButton(
            x_pos, y_pos, box_size[0], box_size[1], color, 0,
            Text(pygame.font.SysFont('Agency FB', 25), text, color_text))

        self.button_board1.change_bg_image(WOOD)
        self.button_board1.add_frame(FRAME)
        self.button_board1.on_click(self.set_and_continue,
                                    GameBoardTypeEnum.ORIGINAL)
        self.sprite_grp.add(self.button_board1)

    def _init_board2(self, x_pos, y_pos, text, color, color_text):
        box_size = (130, 48)
        self.button_board2 = RectButton(
            x_pos, y_pos, box_size[0], box_size[1], color, 0,
            Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.button_board2.on_click(self.set_and_continue,
                                    GameBoardTypeEnum.ALTERNATIVE)
        self.button_board2.change_bg_image(WOOD)
        self.button_board2.add_frame(FRAME)
        self.sprite_grp.add(self.button_board2)

    def _init_board3(self, x_pos, y_pos, text, color, color_text):
        box_size = (130, 48)
        self.button_board3 = RectButton(
            x_pos, y_pos, box_size[0], box_size[1], color, 0,
            Text(pygame.font.SysFont('Agency FB', 25), text, color_text))

        self.button_board3.on_click(self.set_and_continue,
                                    GameBoardTypeEnum.RANDOM)
        self.button_board3.change_bg_image(WOOD)
        self.button_board3.add_frame(FRAME)
        self.sprite_grp.add(self.button_board3)

    def _init_btn_back(self, x_pos: int, y_pos: int, text: str, color: Color,
                       color_text: Color):
        box_size = (130, 48)
        self.buttonBack = RectButton(
            x_pos, y_pos, box_size[0], box_size[1], color, 0,
            Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonBack.change_bg_image(WOOD)
        self.buttonBack.add_frame(FRAME)
        self.buttonBack.on_click(EventQueue.post,
                                 CustomEvent(ChangeSceneEnum.CREATEGAMEMENU))
        self.sprite_grp.add(self.buttonBack)

    @staticmethod
    def set_and_continue(board_type: GameBoardTypeEnum):
        GameStateModel.instance().board_type = board_type
        EventQueue.post(CustomEvent(ChangeSceneEnum.SETMAXPLAYERSCENE))

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

    def update(self, event_queue):
        self.sprite_grp.update(event_queue)
class SetMaxPlayers(object):
    def __init__(self, screen, current_player: PlayerModel):
        self.game_kind = GameStateModel.instance().rules
        self.sprite_grp = pygame.sprite.Group()
        self._current_player = current_player
        self.resolution = (1280, 700)

        self._init_background()
        self._init_title_text()
        #self._init_back_box((int)(1280/2-250), 130, "", Color.GREY, Color.GREEN)

        # COMMENT THIS OUT LATER
        self._init_solo(410, 400, "I'm alone :'(", Color.STANDARDBTN, Color.GREEN2)
        self._init_duo(740, 400, "Duo :'(", Color.STANDARDBTN, Color.GREEN2)
        self._init_button3(410, 200, "3", Color.STANDARDBTN, Color.GREEN2)
        self._init_button4(740, 200, "4", Color.STANDARDBTN, Color.GREEN2)
        self._init_button5(410, 300, "5", Color.STANDARDBTN, Color.GREEN2)
        self._init_button6(740, 300, "6", Color.STANDARDBTN, Color.GREEN2)
        self._init_btn_back(20, 20, "Back", Color.STANDARDBTN, Color.GREEN2)

    def _init_back_box(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', 20), text, color_text))
        self.sprite_grp.add(user_box)

    def _init_title_text(self):
        box_size = (500, 50)
        self.text_title = RectButton((int)(1280/2-250), 60, box_size[0], box_size[1], Color.BLACK, 0,
                                     Text(pygame.font.SysFont('Agency FB', 35), "Set Number of Max Players", Color.GREEN2))
        self.text_title.change_bg_image(WOOD)
        self.text_title.add_frame(FRAME)

        self.sprite_grp.add(self.text_title)

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

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

    def _init_button3(self, x_pos: int, y_pos: int, text: str, color: Color, color_text: Color):
        box_size = (130, 48)
        self.button_players3 = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                     Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.button_players3.on_click(self.set_and_continue, 3)
        self.button_players3.change_bg_image(WOOD)
        self.button_players3.add_frame(FRAME)
        self.sprite_grp.add(self.button_players3)

    def _init_button4(self, x_pos: int, y_pos: int, text: str, color: Color, color_text: Color):
        box_size = (130, 48)
        self.button_players4 = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                     Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.button_players4.change_bg_image(WOOD)
        self.button_players4.add_frame(FRAME)
        self.button_players4.on_click(self.set_and_continue, 4)
        self.sprite_grp.add(self.button_players4)

    def _init_button5(self, x_pos: int, y_pos: int, text: str, color: Color, color_text: Color):
        box_size = (130, 48)
        self.button_players5 = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                     Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.button_players5.change_bg_image(WOOD)
        self.button_players5.add_frame(FRAME)
        self.button_players5.on_click(self.set_and_continue, 5)
        self.sprite_grp.add(self.button_players5)

    def _init_button6(self, x_pos: int, y_pos: int, text: str, color: Color, color_text: Color):
        box_size = (130, 48)
        self.button_players6 = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                     Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.button_players6.on_click(self.set_and_continue, 6)
        self.button_players6.change_bg_image(WOOD)
        self.button_players6.add_frame(FRAME)
        self.sprite_grp.add(self.button_players6)

    def _init_btn_back(self, x_pos: int, y_pos: int, text: str, color: Color, color_text: Color):
        box_size = (130, 48)
        self.buttonBack = RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                     Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonBack.on_click(EventQueue.post, CustomEvent(ChangeSceneEnum.CHOOSEBOARDSCENE))
        self.buttonBack.change_bg_image(WOOD)
        self.buttonBack.add_frame(FRAME)
        self.sprite_grp.add(self.buttonBack)

    @staticmethod
    def set_and_continue(desired_players: int):
        GameStateModel.instance().max_players = desired_players
        Networking.get_instance().create_host()
        EventQueue.post(CustomEvent(ChangeSceneEnum.LOBBYSCENE))

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

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

    def _init_duo(self, x_pos, y_pos, text,color, color_text):
        box_size = (130, 48)
        self.button_duo= RectButton(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                                      Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.button_duo.change_bg_image(WOOD)
        self.button_duo.add_frame(FRAME)
        self.button_duo.on_click(self.set_and_continue, 2)
        self.sprite_grp.add(self.button_duo)
class HostMenuScene(Scene):
    def __init__(self, screen: pygame.Surface, host_player: PlayerModel):
        Scene.__init__(self, screen)
        self._host = host_player

        self._init_background()
        self._init_btn_new_game(575, 481, "New Game", Color.STANDARDBTN,
                                Color.GREEN2)
        self._init_btn_login(575, 371, "Load Game", Color.STANDARDBTN,
                             Color.GREEN2)
        self._init_btn_back(20, 20, "Back", Color.STANDARDBTN, Color.GREEN2)

        self.buttonNewGame.on_click(
            EventQueue.post, CustomEvent(ChangeSceneEnum.CREATEGAMEMENU))
        self.buttonLogin.on_click(EventQueue.post,
                                  CustomEvent(ChangeSceneEnum.LOADGAME))
        self.buttonBack.on_click(
            EventQueue.post,
            CustomEvent(ChangeSceneEnum.HOSTJOINSCENE, player=self._host))

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

    def _init_log_box(self):
        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],
                            Color.GREEN)
        self.sprite_grp.add(log_box)

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

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

    def _init_btn_back(self, x_pos: int, y_pos: int, text: str, color: Color,
                       color_text: Color):
        box_size = (130, 48)
        self.buttonBack = RectButton(
            x_pos, y_pos, box_size[0], box_size[1], color, 0,
            Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        self.buttonBack.change_bg_image(WOOD)
        self.buttonBack.add_frame(FRAME)
        self.sprite_grp.add(self.buttonBack)
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)