Пример #1
0
class ChampionViewer(TextButton):
    def __init__(self, master, assembly_file: str, *args, **kwargs):
        TextButton.__init__(self, master, *args, **kwargs, command=self.select)
        self.file = assembly_file
        self.master = master
        self.comment = get_champion_comment(assembly_file)
        self.selected = False
        self.select_img = Image(IMG["valide"])
        self.select_img.hide()
        master.add(self.select_img)

    def hide_all(self):
        self.hide()
        self.select_img.hide()

    def update(self, *args, **kwargs):
        self.select_img.move(left=self.right + 10, centery=self.centery)

    def select(self):
        self.selected = not self.selected
        if self.selected:
            if len(self.master.selected) >= MAX_NB_PLAYERS:
                self.selected = False
                return
            self.select_img.show()
            self.master.selected.append(self)
        else:
            self.select_img.hide()
            try:
                self.master.selected.remove(self)
            except ValueError:
                pass

    def update_file(self, new_file: str, new_name: str):
        self.file = new_file
        self.set_text(new_name)
        self.comment = get_champion_comment(new_file)
class Gameplay(Window):
    def __init__(self, car_id: int, env: str):
        Window.__init__(self,
                        bg_color=ENVIRONMENT[env],
                        bg_music=RESOURCES.MUSIC["gameplay"])
        self.bind_key(pygame.K_ESCAPE, lambda event: self.pause())
        self.bind_joystick(0, "START", lambda event: self.pause())

        font = RESOURCES.FONT["cooperblack"]

        # Demaraction lines
        self.road = DrawableListVertical(bg_color=GRAY, offset=70)
        self.white_bands = list()
        white_bands_width = 50  #px
        white_lines_height = 10  #px
        for i in range(5):
            if i % 2 == 0:
                self.road.add(
                    RectangleShape(self.width, white_lines_height, WHITE))
            else:
                white_bands = DrawableListHorizontal(offset=20)
                while white_bands.width < self.width:
                    white_bands.add(
                        RectangleShape(white_bands_width, white_lines_height,
                                       WHITE))
                self.road.add(white_bands)
                self.white_bands.append(white_bands)

        # Environment
        self.env_top = DrawableListHorizontal(offset=400)
        self.env_bottom = DrawableListHorizontal(offset=400)
        while self.env_top.width < self.width:
            self.env_top.add(Image(RESOURCES.IMG[env], height=110))
        while self.env_bottom.width < self.width:
            self.env_bottom.add(Image(RESOURCES.IMG[env], height=110))

        #Infos
        params_for_infos = {
            "font": (font, 45),
            "color": YELLOW,
            "shadow": True,
            "shadow_x": 3,
            "shadow_y": 3
        }
        self.infos_score = Info("Score", round_n=0, **params_for_infos)
        self.infos_speed = Info("Speed",
                                extension="km/h",
                                **params_for_infos,
                                justify="right")
        self.infos_distance = Info("Distance",
                                   round_n=2,
                                   extension="km",
                                   **params_for_infos,
                                   justify="right")
        self.infos_time_100 = Info("High speed", **params_for_infos)
        self.infos_time_opposite = Info("Opposite side", **params_for_infos)
        self.clock_time_100 = Clock()
        self.clock_time_opposite = Clock()
        self.total_time_100 = self.total_time_opposite = 0

        self.car = PlayerCar(car_id)
        self.speed = 0
        self.traffic = TrafficCarList(nb_ways=4, max_nb_car=6)
        self.clock_traffic = Clock()
        self.img_crash = Image(RESOURCES.IMG["crash"], size=150)
        self.count_down = CountDown(self,
                                    3,
                                    font=(font, 90),
                                    color=YELLOW,
                                    shadow=True,
                                    shadow_x=5,
                                    shadow_y=5)
        self.last_car_way = 0

        # Background
        self.background = DrawableList(draw=False)
        self.background.add(self.env_top, self.env_bottom, *self.white_bands,
                            self.traffic)

        # Default values
        self.update_clock = Clock()
        self.update_time = 15  #ms
        self.pixel_per_sec = 6  # For 1km/h
        self.pixel_per_ms = self.pixel_per_sec * self.update_time / 1000
        self.paused = False
        self.go_to_garage = self.restart = False
        self.crashed_car = None

        self.disable_key_joy_focus()
        self.init_game()

    def pause(self):
        if not self.count_down.is_shown():
            self.paused = True
            self.car.stop_animation()
            for car in self.traffic:
                car.stop_animation()
        pause = Pause(self)
        pause.mainloop()
        if self.loop and not self.count_down.is_shown():
            self.count_down.start(at_end=self.return_to_game)
            self.objects.set_priority(self.count_down, self.objects.end)

    def return_to_game(self):
        self.paused = False
        self.car.restart_animation()
        for car in self.traffic:
            car.restart_animation()
        self.clock_traffic.tick()
        self.clock_time_100.tick()
        self.clock_time_opposite.tick()
        self.update_clock.tick()

    def init_game(self):
        self.go_to_garage = False
        self.paused = False
        self.crashed_car = None
        for info in (self.infos_speed, self.infos_score, self.infos_distance,
                     self.infos_time_100, self.infos_time_opposite):
            info.value = 0
            if info in (self.infos_time_100, self.infos_time_opposite):
                info.hide()
        self.total_time_100 = self.total_time_opposite = 0
        self.count_down.start()
        self.img_crash.hide()

    def place_objects(self):
        self.count_down.center = self.road.center = self.center
        self.infos_score.move(topleft=(10, 10))
        self.infos_speed.move(right=self.right - 10, top=10)
        self.infos_distance.move(right=self.right - 10,
                                 bottom=self.road.top - 10)
        self.infos_time_100.move(left=10, bottom=self.road.top - 10)
        self.infos_time_opposite.move(left=10, top=self.road.bottom + 10)
        self.car.move(centery=self.road.centery, left=50)
        self.env_top.move(centerx=self.centerx,
                          centery=(self.top + self.road[0].top) / 2)
        self.env_bottom.move(centerx=self.centerx,
                             centery=(self.road[-1].bottom + self.bottom) / 2)

    def update(self):
        if self.paused:
            return
        self.update_player_car()
        if self.update_clock.elapsed_time(self.update_time):
            self.update_infos()
            self.update_background()
            self.update_traffic()
            self.rect_to_update = (self.road.rect, self.env_top.rect,
                                   self.env_bottom.rect, self.infos_score.rect,
                                   self.infos_speed.rect,
                                   self.infos_distance.rect,
                                   self.infos_time_100.rect,
                                   self.infos_time_opposite.rect)

    def update_player_car(self):
        if not self.count_down.is_shown():
            joystick = self.joystick[0]
            controls = SAVE["controls"]
            car_handling = (
                (controls["speed_up"], self.car.speed_up),
                (controls["brake"], self.car.brake),
                (controls["up"], self.car.moveUp),
                (controls["down"], self.car.moveDown),
            )
            for control, car_function in car_handling:
                car_function(self.keyboard.is_pressed(control["key"]))
                car_function(joystick.get_value(control["joy"]))
            if SAVE["auto_acceleration"] is True:
                self.car.speed_up()
        self.car.update(self.pixel_per_ms)
        if self.car.top < self.road[0].bottom + 5:
            self.car.top = self.road[0].bottom + 5
        elif self.car.bottom > self.road[-1].top - 5:
            self.car.bottom = self.road[-1].top - 5
        if not self.car.is_crashed():
            self.speed = self.car.speed
            for car in self.traffic:
                collision = pygame.sprite.collide_mask(self.car, car)
                if collision:
                    self.car.crash(car)
                    self.crashed_car = car
                    self.play_sound(RESOURCES.SFX["crash"])
                    self.img_crash.show()
                    self.img_crash.move(centerx=collision[0] + self.car.left,
                                        centery=collision[1] + self.car.top)
                    self.objects.set_priority(self.img_crash, self.objects.end)
        elif self.car.right <= 0 and self.crashed_car.right <= 0:
            self.end_game()

    def car_in_opposite_side(self) -> bool:
        return bool(self.car.bottom < self.road.centery)

    def update_infos(self):
        min_speed = 30
        score_to_add = (self.car.speed - min_speed) / 5
        bonus = False
        if self.car.speed > 30 and self.car_in_opposite_side():
            self.infos_time_opposite.show()
            self.infos_time_opposite.value = self.clock_time_opposite.get_elapsed_time(
            ) / 1000
            score_to_add += 120
            bonus = True
        else:
            self.total_time_opposite += self.infos_time_opposite.value
            self.infos_time_opposite.value = 0
            self.clock_time_opposite.restart()
            self.infos_time_opposite.hide()
        if self.car.speed >= 100:
            self.infos_time_100.show()
            self.infos_time_100.value = self.clock_time_100.get_elapsed_time(
            ) / 1000
            score_to_add += 150
            bonus = True
        else:
            self.total_time_100 += self.infos_time_100.value
            self.infos_time_100.value = 0
            self.clock_time_100.restart()
            self.infos_time_100.hide()
        if bonus:
            self.infos_score.color = GREEN_DARK
            self.infos_score.shadow_color = YELLOW
        else:
            self.infos_score.color = YELLOW
            self.infos_score.shadow_color = BLACK
        self.infos_score.value += score_to_add * self.update_time / 1000
        self.infos_speed.value = self.car.speed
        self.infos_distance.value += self.car.speed * self.pixel_per_ms / (
            1000 * 3.6)

    def update_background(self):
        offset = self.speed * self.pixel_per_ms
        self.background.move_ip(-offset, 0)
        for white_bands_list in self.white_bands:
            if white_bands_list[0].right <= 0:
                white_bands_list.remove_from_index(0)
            if white_bands_list[-1].right < self.right:
                white_bands_list.add(
                    RectangleShape(*white_bands_list[-1].size, WHITE))
        for env in (self.env_top, self.env_bottom):
            img = env[0]
            if img.right <= 0:
                img.move(left=env[-1].right + env.offset)
                env.set_priority(img, env.end)
        if self.img_crash.is_shown():
            self.img_crash.move_ip(-offset, 0)

    def update_traffic(self):
        for car in self.traffic.drawable:
            car.update(self.pixel_per_ms)
            if car.right < 0:
                self.traffic.remove(car)
        for way, car_list in enumerate(self.traffic.ways, 1):
            for i in range(1, len(car_list)):
                car_1 = car_list[i - 1]
                car_2 = car_list[i]
                if car_2.left - car_1.right < 20:
                    if (way in [1, 2]) and (car_1.speed < car_2.speed):
                        car_2.speed = car_1.speed
                    elif (way in [3, 4]) and (car_1.speed > car_2.speed):
                        car_1.speed = car_2.speed
        ratio = (2 - (round(self.infos_score.value) / 20000)) * 1000
        if self.car.speed > 30 and self.clock_traffic.elapsed_time(ratio):
            if self.traffic.empty(
            ) or self.traffic.last.right < self.right - 20:
                self.traffic.add_cars(self, self.road,
                                      round(self.infos_score.value))

    def end_game(self):
        for car in self.traffic:
            car.stop_animation()
        self.crashed_car = None
        score = round(self.infos_score.value)
        distance = round(self.infos_distance.value, 1)
        time_100 = round(self.total_time_100, 1)
        time_opposite = round(self.total_time_opposite, 1)
        window = EndGame(self, score, distance, time_100, time_opposite)
        window.mainloop()
        if self.restart:
            self.traffic.clear()
            self.car.move(left=50, centery=self.road.centery)
            self.car.restart()
            self.init_game()
Пример #3
0
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 EndGame(Window):
    def __init__(self, master, score: int, distance: float, time_100: float,
                 time_opposite: float):
        Window.__init__(self, master=master, bg_music=master.bg_music)
        self.master = master
        self.bg = RectangleShape(*self.size, (0, 0, 0, 170))
        self.text_score = Text(f"Your score\n{score}",
                               (RESOURCES.FONT["algerian"], 90),
                               YELLOW,
                               justify="center")
        self.img_highscore = Image(RESOURCES.IMG["new_high_score"], width=150)
        if score > SAVE["highscore"]:
            SAVE["highscore"] = score
        else:
            self.img_highscore.hide()

        MAX_MONEY = pow(10, 9) - 1
        money_distance = round(300.40 * distance)
        money_time_100 = round(12.5 * time_100)
        money_time_opposite = round(21.7 * time_opposite)
        money_gained = money_distance + money_time_100 + money_time_opposite
        total = SAVE["money"] + money_gained
        SAVE["money"] = MAX_MONEY if total > MAX_MONEY else total
        self.text_money = Text(format_number(SAVE["money"]),
                               (RESOURCES.FONT["algerian"], 50),
                               YELLOW,
                               img=Image(RESOURCES.IMG["piece"], height=40),
                               compound="right")

        font = ("calibri", 50)
        self.frame = RectangleShape(0.75 * self.width,
                                    0.45 * self.height,
                                    BLACK,
                                    outline=1,
                                    outline_color=WHITE)
        self.text_distance = Text(f"Distance: {distance}", font, WHITE)
        self.img_green_arrow_distance = Image(RESOURCES.IMG["green_arrow"],
                                              height=40)
        self.text_money_distance = Text(money_distance,
                                        font,
                                        WHITE,
                                        img=Image(RESOURCES.IMG["piece"],
                                                  height=40),
                                        compound="right")
        self.text_time_100 = Text(f"Time up to 100: {time_100}", font, WHITE)
        self.img_green_arrow_time_100 = Image(RESOURCES.IMG["green_arrow"],
                                              height=40)
        self.text_money_time_100 = Text(money_time_100,
                                        font,
                                        WHITE,
                                        img=Image(RESOURCES.IMG["piece"],
                                                  height=40),
                                        compound="right")
        self.text_time_opposite = Text(
            f"Time in opposite side: {time_opposite}", font, WHITE)
        self.img_green_arrow_time_opposite = Image(
            RESOURCES.IMG["green_arrow"], height=40)
        self.text_money_time_opposite = Text(money_time_opposite,
                                             font,
                                             WHITE,
                                             img=Image(RESOURCES.IMG["piece"],
                                                       height=40),
                                             compound="right")
        self.total_money = DrawableListHorizontal(offset=10)
        self.total_money.add(
            Text("TOTAL: ", font, WHITE),
            Text(money_gained,
                 font,
                 WHITE,
                 img=Image(RESOURCES.IMG["piece"], height=40),
                 compound="right"))

        params_for_all_buttons = {
            "font": (RESOURCES.FONT["algerian"], 50),
            "bg": GREEN,
            "hover_bg": GREEN_LIGHT,
            "active_bg": GREEN_DARK,
            "hover_sound": RESOURCES.SFX["select"],
            "on_click_sound": RESOURCES.SFX["validate"],
            "outline": 3,
            "highlight_color": YELLOW
        }
        self.menu_buttons = ButtonListHorizontal(offset=30)
        self.menu_buttons.add(
            Button(self,
                   "Restart",
                   **params_for_all_buttons,
                   callback=self.restart_game),
            Button(self,
                   "Garage",
                   **params_for_all_buttons,
                   callback=self.return_to_garage),
            Button(self,
                   "Menu",
                   **params_for_all_buttons,
                   callback=self.return_to_menu))

    def place_objects(self):
        self.text_money.move(top=5, right=self.right - 10)

        self.text_score.move(centerx=self.centerx,
                             centery=self.top + 0.25 * self.height)
        self.img_highscore.move(left=self.text_score.right,
                                centery=self.text_score.centery)

        offset = self.frame.height / 6
        self.frame.move(centerx=self.centerx, top=0.75 * self.centery)
        self.text_distance.move(left=self.frame.left + 5,
                                top=self.frame.top + 10)
        self.text_time_100.move(left=self.frame.left + 5,
                                top=self.text_distance.bottom + offset)
        self.text_time_opposite.move(left=self.frame.left + 5,
                                     top=self.text_time_100.bottom + offset)
        self.img_green_arrow_distance.move(left=self.frame.centerx + 75,
                                           centery=self.text_distance.centery)
        self.img_green_arrow_time_100.move(left=self.frame.centerx + 75,
                                           centery=self.text_time_100.centery)
        self.img_green_arrow_time_opposite.move(
            left=self.frame.centerx + 75,
            centery=self.text_time_opposite.centery)
        self.text_money_distance.move(
            left=self.img_green_arrow_distance.right + 20,
            centery=self.text_distance.centery)
        self.text_money_time_100.move(
            left=self.img_green_arrow_time_100.right + 20,
            centery=self.text_time_100.centery)
        self.text_money_time_opposite.move(
            left=self.img_green_arrow_time_opposite.right + 20,
            centery=self.text_time_opposite.centery)
        self.total_money.move(centerx=self.frame.centerx,
                              bottom=self.frame.bottom - 10)

        self.menu_buttons.move(centerx=self.centerx, bottom=self.bottom - 50)

    def restart_game(self):
        self.master.restart = True
        self.stop()

    def return_to_garage(self):
        self.master.go_to_garage = True
        self.master.stop()
        self.stop()

    def return_to_menu(self):
        self.master.stop()
        self.stop()