Beispiel #1
0
 def __init__(self, master):
     Grid.__init__(self, master, bg_color=(0, 157, 255))
     self.master = master
     self.place_multiple({
         (i, j): NavyGridBox(master, navy=self, size=BOX_SIZE, pos=(i, j))
         for i in range(NB_LINES_BOXES) for j in range(NB_COLUMNS_BOXES)
     })
     self.ships_list = DrawableList()
     self.box_hit_img = DrawableList()
 def __init__(self, nb_ways: int, max_nb_car: int):
     DrawableList.__init__(self)
     self.sprites_traffic_cars = dict()
     for side, car_list in RESOURCES.IMG["traffic"].items():
         self.sprites_traffic_cars[side] = dict()
         for car_id, img_list in car_list.items():
             self.sprites_traffic_cars[side][car_id] = img_list
     self.nb_ways = nb_ways
     self.max_nb_car = max_nb_car
Beispiel #3
0
 def __init__(self, master):
     DrawableListVertical.__init__(self, offset=0, bg_color=(0, 157, 255))
     self.master = master
     for i in range(NB_LINES_BOXES):
         box_line = DrawableListHorizontal(offset=0)
         for j in range(NB_COLUMNS_BOXES):
             box = Box(master, navy=self, size=BOX_SIZE, pos=(i, j))
             box_line.add(box)
         self.add(box_line)
     self.ships_list = DrawableList()
     self.box_hit_img = DrawableList()
    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 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()
Beispiel #6
0
class Navy(DrawableListVertical):

    BOX_NO_HIT = 0
    BOX_HATCH = 1
    BOX_CROSS = 2
    BOX_SHIP_DESTROYED = 3

    def __init__(self, master):
        DrawableListVertical.__init__(self, offset=0, bg_color=(0, 157, 255))
        self.master = master
        for i in range(NB_LINES_BOXES):
            box_line = DrawableListHorizontal(offset=0)
            for j in range(NB_COLUMNS_BOXES):
                box = Box(master, navy=self, size=BOX_SIZE, pos=(i, j))
                box_line.add(box)
            self.add(box_line)
        self.ships_list = DrawableList()
        self.box_hit_img = DrawableList()

    def load_setup(self, setup: Sequence[Dict[str, Any]]) -> None:
        for ship_infos in setup:
            self.add_ship(Ship(**ship_infos))

    def reset(self) -> None:
        self.ships_list.clear()
        self.box_hit_img.clear()
        for box in self.boxes:
            box.reset()

    @property
    def map(self) -> Dict[Tuple[int, int], int]:
        navy_map = {
            box.pos:
            Navy.BOX_NO_HIT if box.state == Button.NORMAL else Navy.BOX_HATCH
            for box in self.boxes
        }
        for box_pos in filter(lambda pos: navy_map[pos] == Navy.BOX_HATCH,
                              navy_map):
            for ship in self.ships:
                if box_pos in ship.boxes_pos:
                    navy_map[
                        box_pos] = Navy.BOX_SHIP_DESTROYED if ship.destroyed(
                        ) else Navy.BOX_CROSS
                    break
        return navy_map

    def after_drawing(self, surface: pygame.Surface) -> None:
        self.ships_list.draw(surface)
        self.box_hit_img.draw(surface)

    def add_ship(self, ship: Ship) -> None:
        self.ships_list.add(ship)
        self.move()

    def get_box(self, line: int, column: int) -> Box:
        return {box.pos: box for box in self.boxes}.get((line, column))

    def set_box_clickable(self, click: bool) -> None:
        for box in self.boxes:
            if click:
                box.enable_key_joy()
                box.enable_mouse()
            else:
                box.disable_key_joy()
                box.disable_mouse()
            box.hover = False

    def destroyed(self) -> bool:
        return len(self.ships) == NB_SHIPS and all(ship.destroyed()
                                                   for ship in self.ships)

    @property
    def boxes(self) -> Sequence[Box]:
        return self.drawable

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

    def move(self, **kwargs):
        DrawableListVertical.move(self, **kwargs)
        for ship in self.ships:
            ship.place_ship(
                list(filter(lambda box: box.pos in ship.boxes_pos,
                            self.boxes)))

    def box_hit(self, box: Box) -> bool:
        return False

    def set_box_hit(self, box: Box, hit: bool) -> None:
        box.state = Button.DISABLED
        hit = bool(hit)
        img = {False: "hatch", True: "cross"}[hit]
        image = Image(RESOURCES.IMG[img], size=box.size)
        image.center = box.center
        self.box_hit_img.add(image)

    def hit_all_boxes_around_ship(self, ship: Ship):
        offsets = [(-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1),
                   (0, 1), (1, 1)]
        for box in ship.boxes_covered:
            line, column = box.pos
            for u, v in offsets:
                box = self.get_box(line + u, column + v)
                if box is None:
                    continue
                if box.state == Button.NORMAL:
                    self.set_box_hit(box, False)
    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()
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()