class Section(Dialog):
    def __init__(self, master, title: str, gameplay: FourInARowGameplay):
        Dialog.__init__(self, master, bg_color=BLUE)
        self.master = master
        self.gameplay = gameplay
        arrow = pygame.transform.flip(RESOURCES.IMG["arrow"], True, False)
        self.button_back = ImageButton(self,
                                       img=arrow,
                                       width=50,
                                       callback=self.stop,
                                       active_offset=(0, 5),
                                       highlight_color=YELLOW)
        self.title = Text(title)

    def place_objects(self) -> None:
        self.button_back.move(left=self.frame.left + 5, top=self.frame.top + 5)
        self.title.move(centerx=self.frame.centerx, top=self.frame.top + 10)

    def on_start_loop(self) -> None:
        self.frame.size = self.frame.width, self.master.buttons.height
        self.frame.move(right=0, top=self.master.buttons.top)
        self.frame.animate_move(self,
                                speed=50,
                                at_every_frame=self.place_objects,
                                left=10,
                                top=self.frame.top)

    def on_quit(self) -> None:
        self.frame.animate_move(self,
                                speed=50,
                                at_every_frame=self.place_objects,
                                right=0,
                                top=self.frame.top)
 def __init__(self, master):
     Window.__init__(self, master=master, bg_music=master.bg_music)
     self.bg = RectangleShape(*self.size, (0, 0, 0, 170))
     self.frame = RectangleShape(0.50 * self.width,
                                 0.50 * self.height,
                                 GREEN,
                                 outline=3)
     self.text = Text("Are you sure you want\nto buy this car ?",
                      (RESOURCES.FONT["algerian"], 60),
                      justify=Text.T_CENTER)
     self.button_yes = Button(self,
                              "Yes",
                              self.text.font,
                              bg=GREEN,
                              hover_bg=GREEN_LIGHT,
                              active_bg=GREEN_DARK,
                              hover_sound=RESOURCES.SFX["select"],
                              on_click_sound=RESOURCES.SFX["validate"],
                              highlight_color=YELLOW,
                              callback=self.buy)
     self.button_red_cross = ImageButton(
         self,
         img=RESOURCES.IMG["red_cross"],
         active_img=RESOURCES.IMG["red_cross_hover"],
         hover_sound=RESOURCES.SFX["select"],
         on_click_sound=RESOURCES.SFX["back"],
         callback=self.stop,
         highlight_color=YELLOW)
     self.buyed = False
     self.bind_key(pygame.K_ESCAPE,
                   lambda event: self.stop(sound=RESOURCES.SFX["back"]))
     self.bind_joystick(
         0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))
Esempio n. 3
0
 def __init__(self, player_id: int):
     Window.__init__(self,
                     bg_color=(0, 200, 255),
                     bg_music=RESOURCES.MUSIC["setup"])
     self.gameplay = Gameplay(player_id)
     self.count_down = CountDown(self,
                                 60,
                                 "Time left: {seconds}",
                                 font=(None, 70),
                                 color=WHITE)
     self.start_count_down = lambda: self.count_down.start(
         at_end=self.timeout) if self.client_socket.connected() else None
     params_for_all_buttons = {
         "bg": GREEN,
         "hover_bg": GREEN_LIGHT,
         "active_bg": GREEN_DARK,
         "highlight_color": YELLOW
     }
     self.button_back = ImageButton(self,
                                    RESOURCES.IMG["arrow_blue"],
                                    **params_for_all_buttons,
                                    rotate=180,
                                    size=50,
                                    callback=self.stop)
     self.navy_grid = DrawableListVertical(offset=0, bg_color=(0, 157, 255))
     for i in range(NB_LINES_BOXES):
         box_line = DrawableListHorizontal(offset=0)
         for j in range(NB_COLUMNS_BOXES):
             box_line.add(BoxSetup(self, size=BOX_SIZE, pos=(i, j)))
         self.navy_grid.add(box_line)
     self.ships_list = DrawableListVertical(offset=70, justify="left")
     for ship_name, ship_infos in SHIPS.items():
         ship_line = DrawableListHorizontal(offset=ship_infos["offset"])
         for _ in range(ship_infos["nb"]):
             ship_line.add(ShipSetup(self, ship_name, ship_infos["size"]))
         self.ships_list.add(ship_line)
     option_size = 50
     self.button_restart = Button.withImageOnly(
         self,
         Image(RESOURCES.IMG["reload_blue"], size=option_size),
         callback=self.reinit_all_ships,
         **params_for_all_buttons)
     self.button_random = Button.withImageOnly(self,
                                               Image(
                                                   RESOURCES.IMG["random"],
                                                   size=option_size),
                                               callback=self.shuffle,
                                               **params_for_all_buttons)
     self.button_play = Button(self,
                               "Play",
                               font=(None, 40),
                               callback=self.play,
                               **params_for_all_buttons)
 def __init__(self, master, title: str, gameplay: FourInARowGameplay):
     Dialog.__init__(self, master, bg_color=BLUE)
     self.master = master
     self.gameplay = gameplay
     arrow = pygame.transform.flip(RESOURCES.IMG["arrow"], True, False)
     self.button_back = ImageButton(self,
                                    img=arrow,
                                    width=50,
                                    callback=self.stop,
                                    active_offset=(0, 5),
                                    highlight_color=YELLOW)
     self.title = Text(title)
Esempio n. 5
0
 def __init__(self):
     Window.__init__(self, bg_color=(0, 200, 255))
     self.player_id = 0
     self.button_back = ImageButton(self, RESOURCES.IMG["arrow_blue"], rotate=180, size=50, callback=self.stop, highlight_color=YELLOW)
     self.player_grid = PlayerNavy(self, self.client_socket)
     self.opposite_grid = OppositeNavy(self, self.client_socket)
     self.ai = AI()
     self.turn_checker = TurnArrow()
     self.restart = False
     self.bind_key(pygame.K_ESCAPE, lambda event: self.stop())
     self.text_finish = Text("Finish !!!", font=(None, 120), color=WHITE)
     self.window_finish = FinishWindow(self)
     self.game_finished = False
    def __init__(self, master):
        Window.__init__(self,
                        bg_color=master.bg_color,
                        bg_music=master.bg_music)
        params_for_button = {
            "highlight_color": YELLOW,
            "hover_sound": RESOURCES.SFX["select"],
            "on_click_sound": RESOURCES.SFX["back"]
        }
        self.master = master
        self.button_back = ImageButton(self,
                                       img=RESOURCES.IMG["blue_arrow"],
                                       **params_for_button,
                                       callback=self.stop)

        self.objects.add(master.text_highscore, master.text_money)

        self.text_title = Text("ENVIRONMENT", (RESOURCES.FONT["algerian"], 90),
                               GREEN_DARK,
                               shadow=True,
                               shadow_x=2,
                               shadow_y=2)
        self.environment = ButtonListHorizontal(offset=15)
        self.texts = DrawableList()
        for name, color in ENVIRONMENT.items():
            b = Button(self,
                       img=Image(RESOURCES.IMG[name],
                                 max_width=180,
                                 max_height=180),
                       compound="center",
                       outline=3,
                       callback=lambda env=name: self.play(env),
                       bg=color,
                       hover_bg=change_saturation(color, -20),
                       active_bg=change_brightness(color, -20),
                       hover_sound=RESOURCES.SFX["select"],
                       on_click_sound=RESOURCES.SFX["validate"],
                       highlight_color=YELLOW)
            b.set_size(200)
            self.texts.add(
                Text(name.upper(), (RESOURCES.FONT["algerian"], 50),
                     GREEN_DARK,
                     shadow=True,
                     shadow_x=2,
                     shadow_y=2))
            self.environment.add(b)

        self.bind_key(pygame.K_ESCAPE,
                      lambda event: self.stop(sound=RESOURCES.SFX["back"]))
        self.bind_joystick(
            0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))
class ConfirmPayement(Window):
    def __init__(self, master):
        Window.__init__(self, master=master, bg_music=master.bg_music)
        self.bg = RectangleShape(*self.size, (0, 0, 0, 170))
        self.frame = RectangleShape(0.50 * self.width,
                                    0.50 * self.height,
                                    GREEN,
                                    outline=3)
        self.text = Text("Are you sure you want\nto buy this car ?",
                         (RESOURCES.FONT["algerian"], 60),
                         justify=Text.T_CENTER)
        self.button_yes = Button(self,
                                 "Yes",
                                 self.text.font,
                                 bg=GREEN,
                                 hover_bg=GREEN_LIGHT,
                                 active_bg=GREEN_DARK,
                                 hover_sound=RESOURCES.SFX["select"],
                                 on_click_sound=RESOURCES.SFX["validate"],
                                 highlight_color=YELLOW,
                                 callback=self.buy)
        self.button_red_cross = ImageButton(
            self,
            img=RESOURCES.IMG["red_cross"],
            active_img=RESOURCES.IMG["red_cross_hover"],
            hover_sound=RESOURCES.SFX["select"],
            on_click_sound=RESOURCES.SFX["back"],
            callback=self.stop,
            highlight_color=YELLOW)
        self.buyed = False
        self.bind_key(pygame.K_ESCAPE,
                      lambda event: self.stop(sound=RESOURCES.SFX["back"]))
        self.bind_joystick(
            0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))

    def place_objects(self):
        self.text.center = self.frame.center = self.center
        self.button_red_cross.move(left=self.frame.left + 5,
                                   top=self.frame.top + 5)
        self.button_yes.move(bottom=self.frame.bottom - 10,
                             centerx=self.frame.centerx)

    def set_grid(self):
        self.button_red_cross.set_obj_on_side(on_bottom=self.button_yes)
        self.button_yes.set_obj_on_side(on_top=self.button_red_cross)

    def buy(self):
        self.buyed = True
        self.stop()
Esempio n. 8
0
    def __init__(self, master: Window):
        Window.__init__(self, bg_color=BACKGROUND_COLOR)
        self.bind_key(pygame.K_ESCAPE, lambda event: self.stop())

        self.master = master
        self.logo = Image(RESOURCES.IMG["logo"])
        arrow = pygame.transform.flip(RESOURCES.IMG["arrow"], True, False)
        self.button_back = ImageButton(self,
                                       img=arrow,
                                       width=100,
                                       callback=self.stop,
                                       active_offset=(0, 5),
                                       highlight_color=YELLOW)
        self.grid = FourInARowGrid(self, self.width / 2, self.height * 0.75)
        self.__player_turn = 0
        self.player_who_start_first = 0
        self.player = 0
        self.__turn = str()
        self.__turn_dict = dict()
        self.__score_player = self.__score_enemy = 0
        self.__highlight_line_window_callback = None
        self.enemy = str()

        self.ai = FourInARowAI()

        self.text_score = Text()
        self.text_player_turn = Text()
        self.left_options = ButtonListVertical(offset=50)
        self.left_options.add(
            Button(self, "Restart", theme="option", callback=self.restart),
            Button(self, "Quit game", theme="option", callback=self.quit_game))
        self.text_winner = Text()
        self.text_drawn_match = Text("Drawn match.")

        self.token_players = Grid(self)
        for row in range(2):
            self.token_players.place(CircleShape(20,
                                                 PLAYER_TOKEN_COLOR[row + 1],
                                                 outline=2,
                                                 outline_color=WHITE),
                                     row,
                                     column=1,
                                     padx=5,
                                     pady=5,
                                     justify="left")

        self.enemy_quit_dialog = EnemyQuitGame(self)
 def __init__(self):
     Window.__init__(self, bg_color=(0, 200, 255))
     self.gameplay = Gameplay()
     self.enemy_quit_window = EnemyQuitGame(self)
     self.transition = GameSetupTransition()
     self.count_down = CountDown(self,
                                 60,
                                 "Time left: {seconds}",
                                 font=(None, 70),
                                 color=WHITE)
     self.start_count_down = lambda: self.count_down.start(
         at_end=self.timeout) if self.client_socket.connected() else None
     self.button_back = ImageButton(self,
                                    RESOURCES.IMG["arrow_blue"],
                                    rotate=180,
                                    size=50,
                                    callback=self.stop)
     self.navy_grid = Grid(self, bg_color=(0, 157, 255))
     self.__boxes_dict = {(i, j): BoxSetup(self, size=BOX_SIZE, pos=(i, j))
                          for i in range(NB_LINES_BOXES)
                          for j in range(NB_COLUMNS_BOXES)}
     self.__boxes_list = list(self.__boxes_dict.values())
     self.navy_grid.place_multiple(self.__boxes_dict)
     self.ships_list = DrawableListVertical(offset=70, justify="left")
     for ship_name, ship_infos in SHIPS.items():
         ship_line = DrawableListHorizontal(offset=ship_infos["offset"])
         for _ in range(ship_infos["nb"]):
             ship_line.add(ShipSetup(self, ship_name, ship_infos["size"]))
         self.ships_list.add(ship_line)
     option_size = 50
     self.button_restart = Button(self,
                                  img=Image(RESOURCES.IMG["reload_blue"],
                                            size=option_size),
                                  callback=self.reinit_all_ships)
     self.button_random = Button(self,
                                 img=Image(RESOURCES.IMG["random"],
                                           size=option_size),
                                 callback=self.shuffle)
     self.button_play = Button(self,
                               "Play",
                               font=(None, 40),
                               callback=self.play)
class Options(Window):
    def __init__(self, master: Window):
        Window.__init__(self, master=master, bg_music=master.bg_music)
        self.frame = RectangleShape(0.60 * self.width,
                                    0.60 * self.height,
                                    GREEN,
                                    outline=3)
        self.title = Text("Options", font=(RESOURCES.FONT["algerian"], 70))

        self.options_font = (RESOURCES.FONT["algerian"], 40)
        self.case_font = (RESOURCES.FONT["algerian"], 30)
        self.control_font = ("calibri", 20)
        params_for_all_scales = {
            "width": 0.45 * self.frame.w,
            "color": TRANSPARENT,
            "scale_color": GREEN_DARK,
            "from_": 0,
            "to": 100,
            "outline": 3,
        }
        params_for_all_buttons = {
            "highlight_color": YELLOW,
            "hover_sound": RESOURCES.SFX["select"],
            "disabled_sound": RESOURCES.SFX["block"]
        }
        params_for_option_buttons = {
            "on_click_sound": RESOURCES.SFX["validate"]
        }
        params_for_buttons = {
            "bg": GRAY_DARK,
            "fg": WHITE,
            "hover_bg": GRAY,
            "active_bg": BLACK
        }
        params_for_reset_button = {
            "bg": RED,
            "fg": WHITE,
            "hover_bg": RED_LIGHT,
            "active_bg": RED_DARK,
        }

        self.button_back = ImageButton(self,
                                       img=RESOURCES.IMG["blue_arrow"],
                                       on_click_sound=RESOURCES.SFX["back"],
                                       callback=self.stop,
                                       **params_for_all_buttons)
        self.button_change_page = Button(self,
                                         ">>",
                                         font=self.case_font,
                                         callback=self.change_page,
                                         **params_for_all_buttons,
                                         **params_for_option_buttons,
                                         **params_for_buttons)
        self.nb_pages = 2
        self.page = 1

        ## PAGE 1 ##
        valid_img = Image(RESOURCES.IMG["green_valid"])
        self.text_music = Text("Music:", self.options_font)
        self.cb_music = CheckBox(self,
                                 30,
                                 30,
                                 TRANSPARENT,
                                 image=valid_img,
                                 value=self.get_music_state(),
                                 callback=self.set_music_state,
                                 **params_for_all_buttons,
                                 **params_for_option_buttons)
        self.scale_music = Scale(
            self,
            **params_for_all_scales,
            **params_for_all_buttons,
            height=self.cb_music.height,
            default=Window.music_volume() * 100,
            callback=lambda value, percent: Window.set_music_volume(percent))
        self.text_sound = Text("SFX:", self.options_font)
        self.cb_sound = CheckBox(self,
                                 30,
                                 30,
                                 TRANSPARENT,
                                 image=valid_img,
                                 value=self.get_sound_state(),
                                 callback=self.set_sound_state,
                                 **params_for_all_buttons,
                                 **params_for_option_buttons)
        self.scale_sound = Scale(
            self,
            **params_for_all_scales,
            **params_for_all_buttons,
            height=self.cb_sound.height,
            default=Window.sound_volume() * 100,
            callback=lambda value, percent: Window.set_sound_volume(percent))
        self.text_fps = Text("FPS:", self.options_font)
        self.cb_show_fps = CheckBox(self,
                                    30,
                                    30,
                                    TRANSPARENT,
                                    image=valid_img,
                                    value=Window.fps_is_shown(),
                                    callback=self.show_fps,
                                    **params_for_all_buttons,
                                    **params_for_option_buttons)
        self.button_reset = Button(self,
                                   "Reset Save",
                                   font=(RESOURCES.FONT["algerian"], 30),
                                   callback=SAVE.reset,
                                   state=Button.DISABLED,
                                   **params_for_all_buttons,
                                   **params_for_option_buttons,
                                   **params_for_reset_button)
        ## PAGE 2 ##
        self.text_acceleration = Text("Accélérer:", self.options_font)
        self.button_auto_acceleration = Button(
            self,
            font=self.case_font,
            callback=lambda: SAVE.update(auto_acceleration=not SAVE[
                "auto_acceleration"]),
            **params_for_all_buttons,
            **params_for_option_buttons,
            **params_for_buttons)
        self.button_acceleration = Button(
            self,
            font=self.control_font,
            callback=lambda: self.choose_key("speed_up"),
            **params_for_all_buttons,
            **params_for_option_buttons,
            **params_for_buttons)
        self.text_brake = Text("Freiner:", self.options_font)
        self.button_brake = Button(self,
                                   font=self.control_font,
                                   callback=lambda: self.choose_key("brake"),
                                   **params_for_all_buttons,
                                   **params_for_option_buttons,
                                   **params_for_buttons)
        self.text_move_up = Text("Aller en haut:", self.options_font)
        self.button_move_up = Button(self,
                                     font=self.control_font,
                                     callback=lambda: self.choose_key("up"),
                                     **params_for_all_buttons,
                                     **params_for_option_buttons,
                                     **params_for_buttons)
        self.text_move_down = Text("Aller en bas:", self.options_font)
        self.button_move_down = Button(
            self,
            font=self.control_font,
            callback=lambda: self.choose_key("down"),
            **params_for_all_buttons,
            **params_for_option_buttons,
            **params_for_buttons)

        self.bind_key(pygame.K_ESCAPE,
                      lambda event: self.stop(sound=RESOURCES.SFX["back"]))
        self.bind_joystick(
            0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))

    def on_quit(self):
        SAVE.dump()

    def change_page(self):
        self.page = (self.page % self.nb_pages) + 1

    def update(self):
        self.hide_all(without=[
            self.frame, self.title, self.button_back, self.button_change_page
        ])
        if self.page == 1:
            self.text_music.show()
            self.text_sound.show()
            for checkbox, scale in [(self.cb_music, self.scale_music),
                                    (self.cb_sound, self.scale_sound)]:
                checkbox.show()
                if checkbox.value is True:
                    scale.show()
                    checkbox.set_obj_on_side(on_right=scale)
                else:
                    checkbox.set_obj_on_side(on_right=self.button_change_page)
            self.text_fps.show()
            self.cb_show_fps.show()
            self.button_reset.show()
            self.button_back.set_obj_on_side(on_bottom=self.cb_music,
                                             on_right=self.cb_music)
            self.button_change_page.set_obj_on_side(on_top=self.cb_show_fps,
                                                    on_left=self.button_reset)
        elif self.page == 2:
            self.text_acceleration.show()
            self.button_auto_acceleration.text = "Automatique" if SAVE[
                "auto_acceleration"] else "Manuel"
            self.button_auto_acceleration.show()
            control_text_format = "Key: {key}\nJoystick: {joy}"
            if not SAVE["auto_acceleration"]:
                self.button_acceleration.text = control_text_format.format(
                    **SAVE["controls"]["speed_up"])
                self.button_acceleration.move(
                    left=self.button_auto_acceleration.right + 10,
                    centery=self.button_auto_acceleration.centery)
                self.button_acceleration.show()
                self.button_auto_acceleration.set_obj_on_side(
                    on_right=self.button_acceleration)
            else:
                self.button_auto_acceleration.set_obj_on_side(
                    on_right=self.button_back)
            fields = [
                (self.text_brake, self.button_brake, "brake"),
                (self.text_move_up, self.button_move_up, "up"),
                (self.text_move_down, self.button_move_down, "down"),
            ]
            for text, button, action in fields:
                text.show()
                button.text = control_text_format.format(
                    **SAVE["controls"][action])
                button.show()
            self.button_back.set_obj_on_side(
                on_bottom=self.button_auto_acceleration,
                on_right=self.button_auto_acceleration)
            self.button_change_page.set_obj_on_side(
                on_top=self.button_move_down, on_left=self.button_move_down)

    def place_objects(self):
        self.frame.move(center=self.center)
        self.title.move(top=self.frame.top + 10, centerx=self.frame.centerx)
        self.button_back.move(top=self.frame.top + 5, left=self.frame.left + 5)
        self.button_change_page.move(bottom=self.frame.bottom - 5,
                                     right=self.frame.right - 5)
        ## PAGE 1 ##
        self.text_music.move(left=self.frame.left + 10,
                             top=self.title.bottom + 10)
        self.text_sound.move(right=self.text_music.right,
                             top=self.text_music.bottom + 5)
        self.cb_music.move(left=self.text_music.right + 10,
                           centery=self.text_music.centery)
        self.cb_sound.move(left=self.text_music.right + 10,
                           centery=self.text_sound.centery)
        self.scale_music.move(centerx=self.frame.centerx,
                              centery=self.cb_music.centery)
        self.scale_music.show_value(Scale.S_RIGHT, font=self.case_font)
        self.scale_sound.move(centerx=self.frame.centerx,
                              centery=self.cb_sound.centery)
        self.scale_sound.show_value(Scale.S_RIGHT, font=self.case_font)
        self.text_fps.move(right=self.text_music.right,
                           top=self.text_sound.bottom + 50)
        self.cb_show_fps.move(left=self.text_fps.right + 10,
                              centery=self.text_fps.centery)
        self.button_reset.move(bottom=self.frame.bottom - 5,
                               left=self.frame.left + 5)
        ## PAGE 2 ##
        self.text_acceleration.move(left=self.frame.left + 10,
                                    top=self.title.bottom + 50)
        self.button_auto_acceleration.move(
            left=self.text_acceleration.right + 10,
            centery=self.text_acceleration.centery)
        self.text_brake.move(left=self.text_acceleration.left,
                             top=self.text_acceleration.bottom + 50)
        self.button_brake.move(left=self.text_brake.right + 10,
                               centery=self.text_brake.centery)
        self.text_move_up.move(left=self.text_acceleration.left,
                               top=self.text_brake.bottom + 50)
        self.button_move_up.move(left=self.text_move_up.right + 10,
                                 centery=self.text_move_up.centery)
        self.text_move_down.move(left=self.text_acceleration.left,
                                 top=self.text_move_up.bottom + 50)
        self.button_move_down.move(left=self.text_move_down.right + 10,
                                   centery=self.text_move_down.centery)

    def set_grid(self):
        ## PAGE 1 ##
        self.cb_music.set_obj_on_side(on_top=self.button_back,
                                      on_left=self.button_back,
                                      on_bottom=self.cb_sound)
        self.scale_music.set_obj_on_side(on_top=self.button_back,
                                         on_left=self.cb_music,
                                         on_bottom=self.scale_sound,
                                         on_right=self.button_change_page)
        self.cb_sound.set_obj_on_side(on_top=self.cb_music,
                                      on_left=self.button_back,
                                      on_bottom=self.cb_show_fps)
        self.scale_sound.set_obj_on_side(on_top=self.scale_music,
                                         on_left=self.cb_sound,
                                         on_bottom=self.cb_show_fps,
                                         on_right=self.button_change_page)
        self.cb_show_fps.set_obj_on_side(on_left=self.button_back,
                                         on_top=self.cb_sound,
                                         on_bottom=self.button_reset,
                                         on_right=self.button_change_page)
        self.button_reset.set_obj_on_side(on_left=self.button_back,
                                          on_top=self.cb_show_fps,
                                          on_right=self.button_change_page)
        ## PAGE 2 ##
        self.button_auto_acceleration.set_obj_on_side(
            on_top=self.button_back,
            on_left=self.button_back,
            on_bottom=self.button_brake)
        self.button_acceleration.set_obj_on_side(
            on_top=self.button_back,
            on_left=self.button_auto_acceleration,
            on_bottom=self.button_brake,
            on_right=self.button_change_page)
        self.button_brake.set_obj_on_side(on_top=self.button_auto_acceleration,
                                          on_left=self.button_back,
                                          on_bottom=self.button_move_up,
                                          on_right=self.button_change_page)
        self.button_move_up.set_obj_on_side(on_top=self.button_brake,
                                            on_left=self.button_back,
                                            on_bottom=self.button_move_down,
                                            on_right=self.button_change_page)
        self.button_move_down.set_obj_on_side(
            on_top=self.button_move_up,
            on_left=self.button_back,
            on_bottom=self.button_change_page,
            on_right=self.button_change_page)

    def choose_key(self, action: str):
        AssignmentPrompt(self, action).mainloop()
Esempio n. 11
0
class FourInARowGameplay(Window):
    def __init__(self, master: Window):
        Window.__init__(self, bg_color=BACKGROUND_COLOR)
        self.bind_key(pygame.K_ESCAPE, lambda event: self.stop())

        self.master = master
        self.logo = Image(RESOURCES.IMG["logo"])
        arrow = pygame.transform.flip(RESOURCES.IMG["arrow"], True, False)
        self.button_back = ImageButton(self,
                                       img=arrow,
                                       width=100,
                                       callback=self.stop,
                                       active_offset=(0, 5),
                                       highlight_color=YELLOW)
        self.grid = FourInARowGrid(self, self.width / 2, self.height * 0.75)
        self.__player_turn = 0
        self.player_who_start_first = 0
        self.player = 0
        self.__turn = str()
        self.__turn_dict = dict()
        self.__score_player = self.__score_enemy = 0
        self.__highlight_line_window_callback = None
        self.enemy = str()

        self.ai = FourInARowAI()

        self.text_score = Text()
        self.text_player_turn = Text()
        self.left_options = ButtonListVertical(offset=50)
        self.left_options.add(
            Button(self, "Restart", theme="option", callback=self.restart),
            Button(self, "Quit game", theme="option", callback=self.quit_game))
        self.text_winner = Text()
        self.text_drawn_match = Text("Drawn match.")

        self.token_players = Grid(self)
        for row in range(2):
            self.token_players.place(CircleShape(20,
                                                 PLAYER_TOKEN_COLOR[row + 1],
                                                 outline=2,
                                                 outline_color=WHITE),
                                     row,
                                     column=1,
                                     padx=5,
                                     pady=5,
                                     justify="left")

        self.enemy_quit_dialog = EnemyQuitGame(self)

    def start(self,
              enemy: str,
              player=1,
              player_name=None,
              enemy_name=None,
              ai_level=None) -> None:
        self.player = player
        self.enemy = enemy
        if enemy == LAN_PLAYER:
            player_name = str(player_name)
            self.client_socket.send("name", player_name)
            result = self.client_socket.wait_for("name")
            if result == self.client_socket.QUIT_MESSAGE:
                return
            enemy_name = str(self.client_socket.get(result))
            self.__turn_dict = {
                1: {
                    1: player_name,
                    2: enemy_name
                }[player],
                2: {
                    1: enemy_name,
                    2: player_name
                }[player]
            }
        else:
            player_name = str(player_name) if player_name is not None else "P1"
            enemy_name = str(enemy_name) if enemy_name is not None else "P2"
            self.__turn_dict = {
                1: "You" if self.enemy == AI else player_name,
                2: "AI" if self.enemy == AI else enemy_name
            }
            if self.enemy == AI:
                self.ai.level = ai_level
        for row, name in enumerate(self.__turn_dict.values()):
            self.token_players.place(Text(name + ":"),
                                     row,
                                     column=0,
                                     padx=5,
                                     pady=5,
                                     justify="right")
        self.mainloop()

    def on_start_loop(self) -> None:
        self.grid[0].focus_set()
        self.score_player = self.score_enemy = 0
        self.player_who_start_first = 0
        self.text_winner.hide()
        self.restart(init=True)

    def on_quit(self) -> None:
        self.stop_connection()

    def quit_game(self) -> None:
        self.stop()
        self.master.stop()

    def restart(self, init=False) -> None:
        if not init:
            self.client_socket.send("restart")
        self.grid.reset()
        self.remove_window_callback(self.__highlight_line_window_callback)
        if self.player_who_start_first == 0:
            if self.enemy == AI:
                self.player_turn = 1
            elif self.enemy == LOCAL_PLAYER or (self.enemy == LAN_PLAYER
                                                and self.player == 1):
                self.player_turn = random.randint(1, 2)
                if self.enemy == LAN_PLAYER:
                    self.client_socket.send("player_turn",
                                            int(self.player_turn))
            elif self.enemy == LAN_PLAYER and self.player == 2:
                result = self.client_socket.wait_for("player_turn")
                if result == self.client_socket.QUIT_MESSAGE:
                    self.stop()
                    return
                self.player_turn = self.client_socket.get(result)
        elif self.text_winner.is_shown():
            self.player_turn = (self.player_who_start_first % 2) + 1
        else:
            self.player_turn = self.player_who_start_first
        self.player_who_start_first = self.player_turn
        self.text_winner.hide()
        self.text_drawn_match.hide()

    def place_objects(self) -> None:
        self.logo.move(centerx=self.centerx, top=10)
        self.grid.midbottom = self.midbottom
        self.text_score.move(left=10, top=self.grid.top)
        self.text_player_turn.move(left=self.text_score.left,
                                   top=self.text_score.bottom + 50)
        self.left_options.move(centerx=(self.left + self.grid.left) // 2,
                               top=self.text_player_turn.bottom + 50)
        self.text_winner.center = ((self.grid.right + self.right) // 2,
                                   self.grid.centery)
        self.token_players.move(centerx=self.text_winner.centerx,
                                top=self.grid.top)
        self.text_drawn_match.center = self.text_winner.center

    def set_grid(self) -> None:
        self.grid.set_obj_on_side(on_top=self.button_back,
                                  on_left=self.left_options[0])
        self.button_back.set_obj_on_side(on_bottom=self.left_options[0],
                                         on_right=self.grid[0])
        self.left_options.set_obj_on_side(on_top=self.button_back,
                                          on_right=self.grid[0])

    @property
    def player_turn(self) -> int:
        return self.__player_turn

    @player_turn.setter
    def player_turn(self, player: int) -> None:
        self.__player_turn = player
        self.__turn = turn = self.__turn_dict[player]
        self.text_player_turn.message = f"Player turn:\n{turn}"
        self.place_objects()
        if self.enemy != LOCAL_PLAYER:
            for column in filter(lambda column: not column.full(),
                                 self.grid.columns):
                column.set_enabled(self.player_turn == self.player)
            if self.enemy == AI and self.player_turn == 2:
                self.after(500, self.play, self.ai.play(self.grid.map))

    @property
    def score_player(self) -> int:
        return self.__score_player

    @score_player.setter
    def score_player(self, value: int) -> None:
        self.__score_player = value
        self.__update_text_score()

    @property
    def score_enemy(self) -> int:
        return self.__score_enemy

    @score_enemy.setter
    def score_enemy(self, value: int) -> None:
        self.__score_enemy = value
        self.__update_text_score()

    def __update_text_score(self) -> None:
        self.text_score.message = "Score:\n{you}: {score_1}\n{enemy}: {score_2}".format(
            you=self.__turn_dict[1],
            enemy=self.__turn_dict[2],
            score_1=self.score_player,
            score_2=self.score_enemy)
        self.place_objects()

    def update(self) -> None:
        if self.enemy == LAN_PLAYER:
            if self.client_socket.recv("column"):
                self.play(self.client_socket.get("column"))
            if self.client_socket.recv("restart"):
                self.restart()
            if self.client_socket.recv(self.client_socket.QUIT_MESSAGE):
                self.enemy_quit_dialog.text.message = "{}\nhas left the game".format(
                    self.__turn_dict[(self.player % 2) + 1])
                self.enemy_quit_dialog.mainloop()

    def play(self, column: int) -> None:
        self.block_only_event([
            pygame.KEYDOWN, pygame.KEYUP, pygame.JOYBUTTONDOWN,
            pygame.JOYBUTTONUP, pygame.MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP
        ])
        if self.enemy == LAN_PLAYER and self.player_turn == self.player:
            self.client_socket.send("column", column)
        self.grid.play(self.player_turn, column)
        line = self.check_victory()
        if line:
            for c in self.grid.columns:
                c.disable()
            self.left_options[0].focus_set()
            self.update_winner()
            self.highlight_line(line)
        elif self.grid.full():
            self.left_options[0].focus_set()
            self.text_drawn_match.show()
        else:
            self.player_turn = (self.player_turn % 2) + 1
            if self.enemy == LOCAL_PLAYER:
                self.draw_and_refresh()
                pygame.time.wait(500)
        self.clear_all_events()
        self.allow_all_events()

    def check_victory(self) -> list[tuple[int, int]]:
        grid = self.grid.map
        grid_pos_getter = [
            lambda row, col, index: (row, col + index),  # Check row (->)
            lambda row, col, index: (row, col - index),  # Check row (<-)
            lambda row, col, index: (row + index, col),  # Check column
            lambda row, col, index:
            (row + index, col - index),  # Check diagonal (/)
            lambda row, col, index:
            (row + index, col + index),  # Check diagonal (\)
        ]
        all_box_pos = list()
        box_pos = list()
        for row, column in filter(lambda pos: grid[pos] != 0, grid):
            for grid_pos in grid_pos_getter:
                index = 0
                box_pos.clear()
                while grid.get(grid_pos(row, column, index),
                               -1) == grid[row, column]:
                    box_pos.append(grid_pos(row, column, index))
                    index += 1
                if len(box_pos) >= 4:
                    all_box_pos.extend(
                        filter(lambda pos: pos not in all_box_pos, box_pos))
        return all_box_pos

    def highlight_line(self, line: list[tuple[int, int]], highlight=True):
        for row, col in line:
            box = self.grid.columns[col].boxes[row]
            if highlight:
                box.circle.color = GREEN
            else:
                box.value = box.value
        self.__highlight_line_window_callback = self.after(
            500, self.highlight_line, line=line, highlight=not highlight)

    def update_winner(self):
        if self.player_turn == 1:
            self.score_player += 1
        else:
            self.score_enemy += 1
        winner = self.__turn
        self.text_winner.message = f"Winner:\n{winner}"
        self.text_winner.show()
    def __init__(self):
        Window.__init__(self,
                        bg_color=GRAY,
                        bg_music=RESOURCES.MUSIC["garage"])
        params_for_all_buttons = {
            "bg": GREEN,
            "hover_bg": GREEN_LIGHT,
            "active_bg": GREEN_DARK,
            "highlight_color": YELLOW,
            "hover_sound": RESOURCES.SFX["select"],
        }
        params_for_button_except_back = {
            "on_click_sound": RESOURCES.SFX["validate"],
            "disabled_sound": RESOURCES.SFX["block"],
            "disabled_bg": GRAY_LIGHT,
        }
        params_for_button_except_back.update(params_for_all_buttons)
        params_for_car_viewer = {
            k: params_for_button_except_back[k]
            for k in ["hover_sound", "on_click_sound"]
        }
        self.button_back = ImageButton(self,
                                       RESOURCES.IMG["blue_arrow"],
                                       **params_for_all_buttons,
                                       on_click_sound=RESOURCES.SFX["back"],
                                       callback=self.stop)
        self.car_viewer = CarViewer(self, SAVE["car"], **params_for_car_viewer)

        size_progress_bar = (300, 30)
        self.speed_bar = ProgressBar(*size_progress_bar, TRANSPARENT, GREEN)
        self.maniability_bar = ProgressBar(*size_progress_bar, TRANSPARENT,
                                           GREEN)
        self.braking_bar = ProgressBar(*size_progress_bar, TRANSPARENT, GREEN)

        self.left_arrow = ImageButton(
            self,
            img=RESOURCES.IMG["left_arrow"],
            active_img=RESOURCES.IMG["left_arrow_hover"],
            **params_for_button_except_back,
            callback=self.car_viewer.decrease_id)
        self.right_arrow = ImageButton(
            self,
            img=RESOURCES.IMG["right_arrow"],
            active_img=RESOURCES.IMG["right_arrow_hover"],
            **params_for_button_except_back,
            callback=self.car_viewer.increase_id)
        for arrow in [self.left_arrow, self.right_arrow]:
            arrow.take_focus(False)
        self.button_price = Button(self,
                                   font=(RESOURCES.FONT["algerian"], 40),
                                   img=Image(RESOURCES.IMG["piece"], size=40),
                                   compound="right",
                                   callback=self.buy_car,
                                   **params_for_button_except_back)
        self.button_play = Button(self,
                                  "Play",
                                  font=(RESOURCES.FONT["algerian"], 70),
                                  callback=self.play,
                                  **params_for_button_except_back)
        self.text_money = Text(format_number(SAVE["money"]),
                               (RESOURCES.FONT["algerian"], 50),
                               YELLOW,
                               img=Image(RESOURCES.IMG["piece"], height=40),
                               compound="right")
        self.text_highscore = Text(
            "Highscore: {}".format(format_number(SAVE["highscore"])),
            (RESOURCES.FONT["algerian"], 50), YELLOW)
        self.padlock = Image(RESOURCES.IMG["padlock"])
        self.bind_key(pygame.K_ESCAPE,
                      lambda event: self.stop(sound=RESOURCES.SFX["back"]))
        self.bind_joystick(
            0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))
class Garage(Window):
    def __init__(self):
        Window.__init__(self,
                        bg_color=GRAY,
                        bg_music=RESOURCES.MUSIC["garage"])
        params_for_all_buttons = {
            "bg": GREEN,
            "hover_bg": GREEN_LIGHT,
            "active_bg": GREEN_DARK,
            "highlight_color": YELLOW,
            "hover_sound": RESOURCES.SFX["select"],
        }
        params_for_button_except_back = {
            "on_click_sound": RESOURCES.SFX["validate"],
            "disabled_sound": RESOURCES.SFX["block"],
            "disabled_bg": GRAY_LIGHT,
        }
        params_for_button_except_back.update(params_for_all_buttons)
        params_for_car_viewer = {
            k: params_for_button_except_back[k]
            for k in ["hover_sound", "on_click_sound"]
        }
        self.button_back = ImageButton(self,
                                       RESOURCES.IMG["blue_arrow"],
                                       **params_for_all_buttons,
                                       on_click_sound=RESOURCES.SFX["back"],
                                       callback=self.stop)
        self.car_viewer = CarViewer(self, SAVE["car"], **params_for_car_viewer)

        size_progress_bar = (300, 30)
        self.speed_bar = ProgressBar(*size_progress_bar, TRANSPARENT, GREEN)
        self.maniability_bar = ProgressBar(*size_progress_bar, TRANSPARENT,
                                           GREEN)
        self.braking_bar = ProgressBar(*size_progress_bar, TRANSPARENT, GREEN)

        self.left_arrow = ImageButton(
            self,
            img=RESOURCES.IMG["left_arrow"],
            active_img=RESOURCES.IMG["left_arrow_hover"],
            **params_for_button_except_back,
            callback=self.car_viewer.decrease_id)
        self.right_arrow = ImageButton(
            self,
            img=RESOURCES.IMG["right_arrow"],
            active_img=RESOURCES.IMG["right_arrow_hover"],
            **params_for_button_except_back,
            callback=self.car_viewer.increase_id)
        for arrow in [self.left_arrow, self.right_arrow]:
            arrow.take_focus(False)
        self.button_price = Button(self,
                                   font=(RESOURCES.FONT["algerian"], 40),
                                   img=Image(RESOURCES.IMG["piece"], size=40),
                                   compound="right",
                                   callback=self.buy_car,
                                   **params_for_button_except_back)
        self.button_play = Button(self,
                                  "Play",
                                  font=(RESOURCES.FONT["algerian"], 70),
                                  callback=self.play,
                                  **params_for_button_except_back)
        self.text_money = Text(format_number(SAVE["money"]),
                               (RESOURCES.FONT["algerian"], 50),
                               YELLOW,
                               img=Image(RESOURCES.IMG["piece"], height=40),
                               compound="right")
        self.text_highscore = Text(
            "Highscore: {}".format(format_number(SAVE["highscore"])),
            (RESOURCES.FONT["algerian"], 50), YELLOW)
        self.padlock = Image(RESOURCES.IMG["padlock"])
        self.bind_key(pygame.K_ESCAPE,
                      lambda event: self.stop(sound=RESOURCES.SFX["back"]))
        self.bind_joystick(
            0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))

    def update(self):
        self.left_arrow.set_visibility(self.car_viewer.id > 1)
        self.right_arrow.set_visibility(
            self.car_viewer.id < len(self.car_viewer))
        if not SAVE["owned_cars"][self.car_viewer.id]:
            self.padlock.show()
            price = self.car_viewer["price"]
            if isinstance(price, int):
                self.button_price.show()
                self.button_price.text = format_number(price)
                self.button_price.state = Button.NORMAL if SAVE[
                    "money"] >= price else Button.DISABLED
            else:
                self.button_price.hide()
            self.button_play.state = Button.DISABLED
        else:
            self.padlock.hide()
            self.button_price.hide()
            self.button_play.state = Button.NORMAL
            SAVE["car"] = self.car_viewer.id
        max_s = self.car_viewer.max_speed
        min_a = self.car_viewer.min_acceleration
        max_m = self.car_viewer.max_maniability
        min_b = self.car_viewer.min_braking
        s = self.car_viewer["max_speed"]
        a = self.car_viewer["acceleration"]
        m = self.car_viewer["maniability"]
        b = self.car_viewer["braking"]
        self.speed_bar.percent = (s + min_a) / (max_s + a)
        self.maniability_bar.percent = m / max_m
        self.braking_bar.percent = min_b / b

    def place_objects(self):
        self.button_back.topleft = (5, 5)
        self.car_viewer.move(center=self.center)
        self.padlock.center = self.car_viewer.center

        self.braking_bar.move(bottom=self.car_viewer.top - 40,
                              centerx=self.car_viewer.centerx + 100)
        self.maniability_bar.move(bottom=self.braking_bar.top - 10,
                                  centerx=self.car_viewer.centerx + 100)
        self.speed_bar.move(bottom=self.maniability_bar.top - 10,
                            centerx=self.car_viewer.centerx + 100)

        self.speed_bar.show_label("Speed/Acc.",
                                  ProgressBar.S_LEFT,
                                  font=(RESOURCES.FONT["algerian"], 40))
        self.maniability_bar.show_label("Maniability",
                                        ProgressBar.S_LEFT,
                                        font=(RESOURCES.FONT["algerian"], 40))
        self.braking_bar.show_label("Braking",
                                    ProgressBar.S_LEFT,
                                    font=(RESOURCES.FONT["algerian"], 40))

        self.left_arrow.move(left=self.left + 50, centery=self.centery)
        self.right_arrow.move(right=self.right - 50, centery=self.centery)
        self.button_price.move(centerx=self.centerx,
                               top=self.car_viewer.bottom + 25)
        self.button_play.move(bottom=self.bottom - 50, right=self.right - 10)

        self.text_money.move(top=5, right=self.right - 10)
        self.text_highscore.move(bottom=self.bottom - 50, left=5)

    def set_grid(self):
        self.button_back.set_obj_on_side(on_bottom=self.car_viewer)
        self.car_viewer.set_obj_on_side(on_top=self.button_back,
                                        on_bottom=self.button_price)
        self.button_price.set_obj_on_side(on_top=self.car_viewer,
                                          on_bottom=self.button_play)
        self.button_play.set_obj_on_side(on_top=self.button_price)

    def buy_car(self):
        confirm_window = ConfirmPayement(self)
        confirm_window.mainloop()
        if confirm_window.buyed:
            SAVE["money"] -= self.car_viewer["price"]
            SAVE["owned_cars"][self.car_viewer.id] = True
            self.text_money.message = format_number(SAVE["money"])
            if Clickable.MODE != Clickable.MODE_MOUSE:
                self.car_viewer.focus_set()

    def play(self):
        environment_chooser = EnvironmentChooser(self)
        environment_chooser.mainloop()
        self.text_money.message = format_number(SAVE["money"])
        self.text_highscore.message = "Highscore: {}".format(
            format_number(SAVE["highscore"]))
class EnvironmentChooser(Window):
    def __init__(self, master):
        Window.__init__(self,
                        bg_color=master.bg_color,
                        bg_music=master.bg_music)
        params_for_button = {
            "highlight_color": YELLOW,
            "hover_sound": RESOURCES.SFX["select"],
            "on_click_sound": RESOURCES.SFX["back"]
        }
        self.master = master
        self.button_back = ImageButton(self,
                                       img=RESOURCES.IMG["blue_arrow"],
                                       **params_for_button,
                                       callback=self.stop)

        self.objects.add(master.text_highscore, master.text_money)

        self.text_title = Text("ENVIRONMENT", (RESOURCES.FONT["algerian"], 90),
                               GREEN_DARK,
                               shadow=True,
                               shadow_x=2,
                               shadow_y=2)
        self.environment = ButtonListHorizontal(offset=15)
        self.texts = DrawableList()
        for name, color in ENVIRONMENT.items():
            b = Button(self,
                       img=Image(RESOURCES.IMG[name],
                                 max_width=180,
                                 max_height=180),
                       compound="center",
                       outline=3,
                       callback=lambda env=name: self.play(env),
                       bg=color,
                       hover_bg=change_saturation(color, -20),
                       active_bg=change_brightness(color, -20),
                       hover_sound=RESOURCES.SFX["select"],
                       on_click_sound=RESOURCES.SFX["validate"],
                       highlight_color=YELLOW)
            b.set_size(200)
            self.texts.add(
                Text(name.upper(), (RESOURCES.FONT["algerian"], 50),
                     GREEN_DARK,
                     shadow=True,
                     shadow_x=2,
                     shadow_y=2))
            self.environment.add(b)

        self.bind_key(pygame.K_ESCAPE,
                      lambda event: self.stop(sound=RESOURCES.SFX["back"]))
        self.bind_joystick(
            0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))

    def place_objects(self):
        self.button_back.topleft = (5, 5)
        self.environment.move(center=self.center)
        self.text_title.move(centerx=self.environment.centerx,
                             bottom=self.environment.top - 10)
        for text, button in zip(self.texts, self.environment):
            text.move(top=button.bottom + 5, centerx=button.centerx)

    def set_grid(self):
        self.environment.set_obj_on_side(on_left=self.button_back,
                                         on_top=self.button_back)
        self.button_back.set_obj_on_side(on_bottom=self.environment[0],
                                         on_right=self.environment[0])
        self.environment[0].focus_set()

    def play(self, env: str):
        gameplay = Gameplay(self.master.car_viewer.id, env)
        gameplay.mainloop()
        if not gameplay.go_to_garage:
            self.master.stop()
        else:
            self.master.car_viewer.focus_set()
        self.stop()
    def __init__(self, master: Window):
        Window.__init__(self, master=master, bg_music=master.bg_music)
        self.frame = RectangleShape(0.60 * self.width,
                                    0.60 * self.height,
                                    GREEN,
                                    outline=3)
        self.title = Text("Options", font=(RESOURCES.FONT["algerian"], 70))

        self.options_font = (RESOURCES.FONT["algerian"], 40)
        self.case_font = (RESOURCES.FONT["algerian"], 30)
        self.control_font = ("calibri", 20)
        params_for_all_scales = {
            "width": 0.45 * self.frame.w,
            "color": TRANSPARENT,
            "scale_color": GREEN_DARK,
            "from_": 0,
            "to": 100,
            "outline": 3,
        }
        params_for_all_buttons = {
            "highlight_color": YELLOW,
            "hover_sound": RESOURCES.SFX["select"],
            "disabled_sound": RESOURCES.SFX["block"]
        }
        params_for_option_buttons = {
            "on_click_sound": RESOURCES.SFX["validate"]
        }
        params_for_buttons = {
            "bg": GRAY_DARK,
            "fg": WHITE,
            "hover_bg": GRAY,
            "active_bg": BLACK
        }
        params_for_reset_button = {
            "bg": RED,
            "fg": WHITE,
            "hover_bg": RED_LIGHT,
            "active_bg": RED_DARK,
        }

        self.button_back = ImageButton(self,
                                       img=RESOURCES.IMG["blue_arrow"],
                                       on_click_sound=RESOURCES.SFX["back"],
                                       callback=self.stop,
                                       **params_for_all_buttons)
        self.button_change_page = Button(self,
                                         ">>",
                                         font=self.case_font,
                                         callback=self.change_page,
                                         **params_for_all_buttons,
                                         **params_for_option_buttons,
                                         **params_for_buttons)
        self.nb_pages = 2
        self.page = 1

        ## PAGE 1 ##
        valid_img = Image(RESOURCES.IMG["green_valid"])
        self.text_music = Text("Music:", self.options_font)
        self.cb_music = CheckBox(self,
                                 30,
                                 30,
                                 TRANSPARENT,
                                 image=valid_img,
                                 value=self.get_music_state(),
                                 callback=self.set_music_state,
                                 **params_for_all_buttons,
                                 **params_for_option_buttons)
        self.scale_music = Scale(
            self,
            **params_for_all_scales,
            **params_for_all_buttons,
            height=self.cb_music.height,
            default=Window.music_volume() * 100,
            callback=lambda value, percent: Window.set_music_volume(percent))
        self.text_sound = Text("SFX:", self.options_font)
        self.cb_sound = CheckBox(self,
                                 30,
                                 30,
                                 TRANSPARENT,
                                 image=valid_img,
                                 value=self.get_sound_state(),
                                 callback=self.set_sound_state,
                                 **params_for_all_buttons,
                                 **params_for_option_buttons)
        self.scale_sound = Scale(
            self,
            **params_for_all_scales,
            **params_for_all_buttons,
            height=self.cb_sound.height,
            default=Window.sound_volume() * 100,
            callback=lambda value, percent: Window.set_sound_volume(percent))
        self.text_fps = Text("FPS:", self.options_font)
        self.cb_show_fps = CheckBox(self,
                                    30,
                                    30,
                                    TRANSPARENT,
                                    image=valid_img,
                                    value=Window.fps_is_shown(),
                                    callback=self.show_fps,
                                    **params_for_all_buttons,
                                    **params_for_option_buttons)
        self.button_reset = Button(self,
                                   "Reset Save",
                                   font=(RESOURCES.FONT["algerian"], 30),
                                   callback=SAVE.reset,
                                   state=Button.DISABLED,
                                   **params_for_all_buttons,
                                   **params_for_option_buttons,
                                   **params_for_reset_button)
        ## PAGE 2 ##
        self.text_acceleration = Text("Accélérer:", self.options_font)
        self.button_auto_acceleration = Button(
            self,
            font=self.case_font,
            callback=lambda: SAVE.update(auto_acceleration=not SAVE[
                "auto_acceleration"]),
            **params_for_all_buttons,
            **params_for_option_buttons,
            **params_for_buttons)
        self.button_acceleration = Button(
            self,
            font=self.control_font,
            callback=lambda: self.choose_key("speed_up"),
            **params_for_all_buttons,
            **params_for_option_buttons,
            **params_for_buttons)
        self.text_brake = Text("Freiner:", self.options_font)
        self.button_brake = Button(self,
                                   font=self.control_font,
                                   callback=lambda: self.choose_key("brake"),
                                   **params_for_all_buttons,
                                   **params_for_option_buttons,
                                   **params_for_buttons)
        self.text_move_up = Text("Aller en haut:", self.options_font)
        self.button_move_up = Button(self,
                                     font=self.control_font,
                                     callback=lambda: self.choose_key("up"),
                                     **params_for_all_buttons,
                                     **params_for_option_buttons,
                                     **params_for_buttons)
        self.text_move_down = Text("Aller en bas:", self.options_font)
        self.button_move_down = Button(
            self,
            font=self.control_font,
            callback=lambda: self.choose_key("down"),
            **params_for_all_buttons,
            **params_for_option_buttons,
            **params_for_buttons)

        self.bind_key(pygame.K_ESCAPE,
                      lambda event: self.stop(sound=RESOURCES.SFX["back"]))
        self.bind_joystick(
            0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))
Esempio n. 16
0
class Gameplay(Window):
    def __init__(self, player: int):
        Window.__init__(self,
                        bg_color=(0, 200, 255),
                        bg_music=RESOURCES.MUSIC["gameplay"])
        self.player_id = player
        self.button_back = ImageButton(self,
                                       RESOURCES.IMG["arrow_blue"],
                                       rotate=180,
                                       size=50,
                                       callback=self.stop,
                                       highlight_color=YELLOW)
        self.player_grid = PlayerNavy(self, self.client_socket)
        self.opposite_grid = OppositeNavy(self, self.client_socket)
        self.ai = AI()
        self.turn_checker = TurnArrow()
        self.restart = False
        self.bind_key(pygame.K_ESCAPE, lambda event: self.stop())
        self.text_finish = Text("Finish !!!", font=(None, 120), color=WHITE)
        self.game_finished = False

    def start(self,
              navy_setup: Sequence[Dict[str, Any]],
              ai_setup=None) -> None:
        self.player_grid.load_setup(navy_setup)
        self.opposite_grid.ai_setup = ai_setup or list()
        self.turn_checker.turn = self.get_default_turn()
        self.game_finished = self.restart = False
        self.ai.reset()
        self.mainloop()

    def on_quit(self) -> None:
        self.player_grid.reset()
        self.opposite_grid.reset()
        self.objects.set_focus(None)

    def update(self):
        self.text_finish.set_visibility(self.game_finished)
        if self.game_finished:
            return
        if self.player_grid.destroyed():
            self.opposite_grid.set_box_clickable(False)
            self.highlight_ships(
                self.opposite_grid.show_all_non_destroyed_ships())
            self.after(3000, lambda victory=False: self.finish(victory))
            self.game_finished = True
        elif self.opposite_grid.destroyed():
            self.opposite_grid.set_box_clickable(False)
            self.player_grid.send_non_destroyed_ships()
            self.after(3000, lambda victory=True: self.finish(victory))
            self.game_finished = True
        elif self.client_socket.connected():
            if self.client_socket.recv("attack"):
                self.hit_a_box(self.player_grid,
                               json.loads(self.client_socket.get("attack")))
            elif self.client_socket.recv("quit"):
                self.finish(None)

    def get_default_turn(self) -> bool:
        if not self.client_socket.connected():
            return True
        if self.player_id == 1:
            my_turn = random.choice([True, False])
            self.client_socket.send("turn", not my_turn)
            return my_turn
        result = self.client_socket.wait_for("turn")
        if result == "quit":
            return False
        return bool(self.client_socket.get("turn"))

    def finish(self, victory: bool):
        FinishWindow(self, victory).mainloop()
        self.stop()

    def highlight_ships(self, ships: Sequence[Ship]):
        for ship in ships:
            for box in ship.boxes_covered:
                box.hover = not box.hover
        self.after(500, lambda: self.highlight_ships(ships))

    def place_objects(self):
        self.button_back.move(x=20, y=20)
        self.text_finish.move(y=20, centerx=self.centerx)
        self.player_grid.move(x=20, centery=self.centery)
        self.opposite_grid.move(right=self.right - 20, centery=self.centery)
        self.turn_checker.resize_all_sprites(width=self.opposite_grid.left -
                                             self.player_grid.right - 150)
        self.turn_checker.move(center=self.center)

    def hit_a_box(self, navy: Navy, box: Union[Tuple[int, int], Box]):
        if isinstance(box, (list, tuple)):
            box = navy.get_box(*box)
        hitted = navy.box_hit(box)
        if navy.destroyed():
            return
        turn = hitted if navy == self.opposite_grid else not hitted
        if turn is False:
            self.opposite_grid.set_box_clickable(False)
        wait_time = 1000 if turn != self.turn_checker.turn else 0
        self.after(wait_time, lambda: self.set_turn(turn))

    def set_turn(self, turn: bool):
        self.turn_checker.turn = turn
        if self.turn_checker.turn is True:
            self.opposite_grid.set_box_clickable(True)
        if self.turn_checker.turn is False and not self.client_socket.connected(
        ) and not self.player_grid.destroyed():
            self.after(
                1000, lambda: self.hit_a_box(
                    self.player_grid, self.ai.play(self.player_grid.map)))
Esempio n. 17
0
class NavySetup(Window):
    def __init__(self):
        Window.__init__(self, bg_color=(0, 200, 255))
        self.gameplay = Gameplay()
        self.enemy_quit_window = EnemyQuitGame(self)
        self.transition = GameSetupTransition()
        self.count_down = CountDown(self,
                                    60,
                                    "Time left: {seconds}",
                                    font=(None, 70),
                                    color=WHITE)
        self.start_count_down = lambda: self.count_down.start(
            at_end=self.timeout) if self.client_socket.connected() else None
        self.button_back = ImageButton(self,
                                       RESOURCES.IMG["arrow_blue"],
                                       rotate=180,
                                       size=50,
                                       callback=self.stop)
        self.navy_grid = Grid(self, bg_color=(0, 157, 255))
        self.__boxes_dict = {(i, j): BoxSetup(self, size=BOX_SIZE, pos=(i, j))
                             for i in range(NB_LINES_BOXES)
                             for j in range(NB_COLUMNS_BOXES)}
        self.__boxes_list = list(self.__boxes_dict.values())
        self.navy_grid.place_multiple(self.__boxes_dict)
        self.ships_list = DrawableListVertical(offset=70, justify="left")
        for ship_name, ship_infos in SHIPS.items():
            ship_line = DrawableListHorizontal(offset=ship_infos["offset"])
            for _ in range(ship_infos["nb"]):
                ship_line.add(ShipSetup(self, ship_name, ship_infos["size"]))
            self.ships_list.add(ship_line)
        option_size = 50
        self.button_restart = Button(self,
                                     img=Image(RESOURCES.IMG["reload_blue"],
                                               size=option_size),
                                     callback=self.reinit_all_ships)
        self.button_random = Button(self,
                                    img=Image(RESOURCES.IMG["random"],
                                              size=option_size),
                                    callback=self.shuffle)
        self.button_play = Button(self,
                                  "Play",
                                  font=(None, 40),
                                  callback=self.play)

    @property
    def ships(self) -> Sequence[ShipSetup]:
        return self.ships_list.drawable

    @property
    def boxes(self) -> Sequence[BoxSetup]:
        return self.__boxes_list

    def start(self, player_id: int) -> None:
        self.gameplay.player_id = player_id
        self.mainloop(transition=self.transition)

    def on_start_loop(self) -> None:
        self.start_count_down()

    def on_quit(self) -> None:
        self.reinit_all_ships()

    def place_objects(self) -> None:
        self.button_back.move(x=20, y=20)
        self.count_down.move(top=20, right=self.right - 20)
        self.navy_grid.move(x=20, centery=self.centery)
        self.ships_list.move(left=self.navy_grid.right + 100,
                             top=self.navy_grid.top + 30)
        self.button_restart.move(left=self.navy_grid.right + 20,
                                 bottom=self.navy_grid.bottom)
        self.button_random.move(left=self.button_restart.right + 20,
                                bottom=self.navy_grid.bottom)
        self.button_play.move(right=self.right - 20, bottom=self.bottom - 20)
        for ship in self.ships:
            ship.default_center = ship.center

    def update(self):
        self.button_play.state = Button.NORMAL if all(
            ship.on_map for ship in self.ships) else Button.DISABLED
        if self.client_socket.recv("quit"):
            self.count_down.stop()
            self.enemy_quit_window.mainloop()
            self.stop()

    def create_setup(self) -> Sequence[dict[str, dict[str, Any]]]:
        setup = list()
        for ship in self.ships:
            setup.append({
                "name": ship.name,
                "orient": ship.orient,
                "boxes": [box.pos for box in ship.boxes_covered]
            })
        return setup

    def timeout(self):
        for ship in filter(lambda ship: not ship.on_map, self.ships):
            self.set_random_position_for_ship(ship)
        self.play()

    def play(self):
        if not all(ship.on_map for ship in self.ships):
            return
        if not self.client_socket.connected():
            ai_navy_setup = NavySetup()
            ai_navy_setup.shuffle()
            ai_setup = ai_navy_setup.create_setup()
        else:
            ai_setup = None
            self.count_down.stop()
            self.client_socket.send("ready")
            WaitEnemy(self).mainloop()
        self.gameplay.start(self.create_setup(), ai_setup=ai_setup)
        self.reinit_all_ships()
        if self.gameplay.restart:
            self.start_count_down()
        else:
            self.stop()

    def reinit_all_ships(self):
        for ship in self.ships:
            ship.center = ship.default_center
            ship.orient = ShipSetup.HORIZONTAL
            ship.clear()

    def get_box(self, line: int, column: float) -> BoxSetup:
        return self.__boxes_dict.get((line, column))

    def remove_boxes_highlight(self):
        for box in self.boxes:
            box.hover = False
            box.state = Button.NORMAL

    def get_valid_highlighted_boxes(self) -> Sequence[BoxSetup]:
        return list(
            filter(lambda box: box.hover and box.state == Button.NORMAL,
                   self.boxes))

    def highlight_boxes(self, ship: ShipSetup) -> None:
        boxes = list()
        for box in self.boxes:
            self.highlight_one_box(ship, box, len(boxes))
            if box.hover is True:
                boxes.append(box)
        if len(boxes) != ship.ship_size or any(not self.valid_box(ship, box)
                                               for box in boxes):
            for box in boxes:
                box.state = Button.DISABLED

    def highlight_one_box(self, ship: ShipSetup, box: BoxSetup,
                          nb_boxes_covered: int) -> None:
        box.hover = False
        box.state = Button.NORMAL
        if nb_boxes_covered == ship.ship_size:
            return
        if ship.orient == ShipSetup.HORIZONTAL:
            if (box.top <= ship.centery <= box.bottom) is False:
                return
            if ship.left > box.centerx or ship.right < box.centerx:
                return
        else:
            if (box.left <= ship.centerx <= box.right) is False:
                return
            if ship.top > box.centery or ship.bottom < box.centery:
                return
        box.hover = True

    def valid_box(self, ship: ShipSetup, box: BoxSetup) -> bool:
        line, column = box.pos
        offsets = [(-1, -1), (0, -1), (1, -1), (-1, 0), (0, 0), (1, 0),
                   (-1, 1), (0, 1), (1, 1)]
        for u, v in offsets:
            box = self.get_box(line + u, column + v)
            if box is None:
                continue
            if box.ship is not None and box.ship != ship:
                return False
        return True

    def shuffle(self) -> None:
        self.reinit_all_ships()
        for ship in self.ships:
            self.set_random_position_for_ship(ship)

    def set_random_position_for_ship(self, ship: ShipSetup) -> None:
        ship.orient = random.choice([ShipSetup.HORIZONTAL, ShipSetup.VERTICAL])
        first_box = random.choice(self.get_available_boxes(ship))
        boxes = [first_box]
        for i in range(1, ship.ship_size):
            u = first_box.pos[
                0] + i if ship.orient == ShipSetup.VERTICAL else first_box.pos[
                    0]
            v = first_box.pos[
                1] + i if ship.orient == ShipSetup.HORIZONTAL else first_box.pos[
                    1]
            boxes.append(self.get_box(u, v))
        ship.place_ship_on_map(boxes)

    def get_available_boxes(self, ship: ShipSetup):
        available_boxes = list()
        for box in self.boxes:
            if not self.valid_box(ship, box):
                continue
            line, column = box.pos
            valid = True
            for i in range(1, ship.ship_size):
                u = line + i if ship.orient == ShipSetup.VERTICAL else line
                v = column + i if ship.orient == ShipSetup.HORIZONTAL else column
                b = self.get_box(u, v)
                if b is None or (not self.valid_box(ship, b)):
                    valid = False
                    break
            if valid:
                available_boxes.append(box)
        return available_boxes