Beispiel #1
0
def start(screen: pygame.surface.Surface):
    is_game_open = True
    clock = pygame.time.Clock()  # Часы

    # Игрок
    player = Player(screen.get_width() * 0.5, screen.get_height() * 0.5)
    # Группа со спрайтами игрока и его приуела
    player_sprites = pygame.sprite.Group()
    player_sprites.add(player)
    player_sprites.add(player.scope)

    # Фоновая музыка
    # FIXME: место на котором игра пролагивает (Никита пофиксит)
    pygame.mixer.music.load(os.path.join("assets/audio", "game_bg.ogg"))
    pygame.mixer.music.play(-1)
    pygame.mixer.music.set_volume(DEFAULT_MUSIC_VOLUME)

    # Игровой цикл
    while is_game_open:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                is_game_open = True
                break

        # Очистка экрана
        screen.fill((255, 255, 255))
        # Обновляем и выводим все спрайты
        player_sprites.update()
        player_sprites.draw(screen)

        clock.tick(FPS)
        pygame.display.flip()
Beispiel #2
0
 def draw(self, screen: pygame.surface.Surface):
     for pos in self.pos:
         # 绘制蛇身
         rect = pygame.rect.Rect(pos[0] * config.horzInr,
                                 pos[1] * config.vertInr,
                                 config.horzInr + 2, config.vertInr + 2)
         color = (0, 0, 255)
         screen.fill(color, rect)
         # 绘制蛇的两个眼睛
         if pos == self.pos[0]:
             rectL = rect
             rectL.width /= 4
             rectL.height /= 4
             rectR = rectL.copy()
             curDir = self.getCurDir()
             if curDir == Direction.UP:
                 rectL.center = (pos[0] * config.horzInr +
                                 config.horzInr / 4,
                                 pos[1] * config.vertInr +
                                 config.vertInr / 4)
                 rectR.center = (pos[0] * config.horzInr +
                                 config.horzInr / 4 * 3,
                                 pos[1] * config.vertInr +
                                 config.vertInr / 4)
             elif curDir == Direction.DOWN:
                 rectL.center = (pos[0] * config.horzInr +
                                 config.horzInr / 4 * 3,
                                 pos[1] * config.vertInr +
                                 config.vertInr / 4 * 3)
                 rectR.center = (pos[0] * config.horzInr +
                                 config.horzInr / 4,
                                 pos[1] * config.vertInr +
                                 config.vertInr / 4 * 3)
             elif curDir == Direction.LEFT:
                 rectL.center = (pos[0] * config.horzInr +
                                 config.horzInr / 4,
                                 pos[1] * config.vertInr +
                                 config.vertInr / 4 * 3)
                 rectR.center = (pos[0] * config.horzInr +
                                 config.horzInr / 4,
                                 pos[1] * config.vertInr +
                                 config.vertInr / 4)
             elif curDir == Direction.RIGHT:
                 rectL.center = (pos[0] * config.horzInr +
                                 config.horzInr / 4 * 3,
                                 pos[1] * config.vertInr +
                                 config.vertInr / 4)
                 rectR.center = (pos[0] * config.horzInr +
                                 config.horzInr / 4 * 3,
                                 pos[1] * config.vertInr +
                                 config.vertInr / 4 * 3)
             color = (250, 235, 215)
             pygame.draw.ellipse(screen, color, rectL)
             pygame.draw.ellipse(screen, color, rectR)
Beispiel #3
0
def main_menu(surface: pygame.surface.Surface):
    """
    Initiates a few required variables
    (GUI management, fonts, text)
    """
    gui_manager = pygame_gui.UIManager(
        (constants.window_width, constants.window_height),
        'main_menu_theme.json')
    clock = pygame.time.Clock()
    font = pygame.font.Font("ARCADECLASSIC.TTF", 98, bold=True)
    title_img = font.render("Smart Asteroids", True, (200, 200, 200, 200),
                            background_color)
    title_rect = title_img.get_rect()
    title_rect.center = (constants.window_width * 0.5,
                         constants.window_height * 235 / 720)
    title_rect.size = (constants.window_width * 700 // 1280,
                       constants.window_height * 250 // 720)
    play_button_rect = pygame.Rect((constants.window_width * 470 // 1280,
                                    constants.window_height * 405 // 720),
                                   (constants.window_width * 340 // 1280,
                                    constants.window_height * 80 // 720))
    play_button = pygame_gui.elements.UIButton(relative_rect=play_button_rect,
                                               text="Play",
                                               manager=gui_manager)
    quit_button_rect = pygame.Rect((constants.window_width * 470 // 1280,
                                    constants.window_height * 529 // 720),
                                   (constants.window_width * 340 // 1280,
                                    constants.window_height * 80 / 720))
    quit_button = pygame_gui.elements.UIButton(relative_rect=quit_button_rect,
                                               text="Quit",
                                               manager=gui_manager)

    is_running = True
    while is_running:
        dt = clock.tick(60) / 1000.0
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                is_running = False
            if event.type == pygame.USEREVENT:
                if event.user_type == pygame_gui.UI_BUTTON_PRESSED:
                    if event.ui_element == play_button:
                        return game_states.GAME_STATES.IN_GAME
                    elif event.ui_element == quit_button:
                        return game_states.GAME_STATES.QUIT
            gui_manager.process_events(event)

        gui_manager.update(dt)

        surface.fill(background_color)
        surface.blit(title_img, title_rect)
        gui_manager.draw_ui(surface)

        pygame.display.update()
Beispiel #4
0
    def fall(self,
             gameObject: Game,
             fen: pygame.surface.Surface,
             frames: int = 30):  #Animation to do
        start_pos = (self.p.x + self.p.w, self.p.y)
        alphas = [pi / (2 * frames) * i for i in range(frames + 1)][::-1]

        for alpha in alphas:
            fen.fill((0, 0, 0))
            end_pos = (start_pos[0] + self.l * cos(-alpha),
                       start_pos[1] + self.l * sin(-alpha))

            pygame.draw.line(fen, (0, 255, 0), start_pos, end_pos, 1)
            gameObject.rendering([False, True, False, True])
Beispiel #5
0
def result(displaysurf: pg.surface.Surface, clock: pg.time.Clock, diff: str,
           diff_color: Tuple[int, int, int], score: int) -> None:
    """스코어보드를 업데이트하고 출력한다.

    Args:
        displaysurf: init 함수에 의해 반환된 최상위 Surface
        clock: init 함수에 의해 반환된 Clock
        diff: prompt_difficulty 함수에 의해 반환된 난이도
        diff_color: prompt_difficulty 함수에 의해 반환된 난이도에 해당하는 색상
        score: game 함수에 의해 반환된 점수

    """
    scorefile: Path = Path.cwd() / ct.SCOREDIR / f"{diff}.pkl"

    scores: List[int] = []

    try:
        scores = pickle.load(scorefile.open("rb"))
    except FileNotFoundError:
        pass

    scores.append(score)
    scores.sort()
    scores.reverse()
    scores = scores[:5]

    pickle.dump(scores, scorefile.open("wb"))

    displaysurf.fill(ct.BLACK)
    write_text_ct(displaysurf, 60, (ct.WIDTH / 2, ct.HEIGHT * 0.15),
                  f'Score ({diff})', diff_color)

    for i, sco in enumerate(scores):
        write_text_ct(displaysurf, 40,
                      (ct.WIDTH / 2, ct.HEIGHT * (0.3 + 0.1 * i)),
                      f'{i + 1}. {sco}', ct.WHITE)

    write_text_ct(displaysurf, 40, (ct.WIDTH / 2, ct.HEIGHT * 0.85),
                  f'Your score: {score}', ct.WHITE)

    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT\
               or (event.type == pg.KEYDOWN and event.key == ord('q')):  # 종료
                pg.quit()
                sys.exit()

        pg.display.update()
        clock.tick(ct.FPS)
    def draw_colourless_rounded_rectangle(
            large_corner_radius: int,
            large_shape_surface: pygame.surface.Surface,
            clear_colour_string: str = '#00000000',
            corner_offset: int = 0):
        """
        Draw a rounded rectangle shape in pure white so it is ready to be multiplied by a colour
        or gradient.

        :param large_corner_radius: The radius of the corners.
        :param large_shape_surface: The surface to draw onto, the shape fills the surface.
        :param clear_colour_string: The colour to clear the background to.
        :param corner_offset: Offsets the corners, used to help avoid overlaps that look bad.

        """
        if pygame.version.vernum[0] >= 2 and PYGAME_DEV_NUM >= 8:
            pygame.draw.rect(
                large_shape_surface,
                pygame.Color('#FFFFFFFF'),
                pygame.Rect(
                    (corner_offset, corner_offset),
                    (large_shape_surface.get_width() - corner_offset,
                     large_shape_surface.get_height() - corner_offset)),
                border_radius=large_corner_radius)
        else:
            pygame.draw.circle(large_shape_surface, pygame.Color('#FFFFFFFF'),
                               (large_corner_radius + corner_offset,
                                large_corner_radius + corner_offset),
                               large_corner_radius)
            if corner_offset > 0:
                large_shape_surface.fill(
                    pygame.Color(clear_colour_string),
                    pygame.Rect(0, int(large_shape_surface.get_height() / 2),
                                large_shape_surface.get_width(),
                                int(large_shape_surface.get_height() / 2)))
                large_shape_surface.fill(
                    pygame.Color(clear_colour_string),
                    pygame.Rect(int(large_shape_surface.get_width() / 2), 0,
                                int(large_shape_surface.get_width() / 2),
                                large_shape_surface.get_height()))

            x_flip = pygame.transform.flip(large_shape_surface, True, False)
            large_shape_surface.blit(x_flip, (0, 0))
            y_flip = pygame.transform.flip(large_shape_surface, False, True)
            large_shape_surface.blit(y_flip, (0, 0))
            large_shape_surface.fill(
                pygame.Color("#FFFFFFFF"),
                pygame.Rect((large_corner_radius, 0),
                            (large_shape_surface.get_width() -
                             (2 * large_corner_radius),
                             large_shape_surface.get_height())))
            large_shape_surface.fill(
                pygame.Color("#FFFFFFFF"),
                pygame.Rect((0, large_corner_radius),
                            (large_shape_surface.get_width(),
                             large_shape_surface.get_height() -
                             (2 * large_corner_radius))))
Beispiel #7
0
def loading_screen(screen: pygame.surface.Surface) -> None:
    """
    Функция, устанавливающая псевдо загрузочный экран
    :param screen: Поверхность с экраном, где отрисовывается экран загрузки
    """
    # Центральная точка на экране для вывода текста
    central_point = (screen.get_width() * 0.5, screen.get_height() * 0.5)
    # Шрифт для текста
    font = load_game_font(font_size=48)
    for i in range(4):
        text = font.render('Загрузка' + '.' * i, True, (240, 240, 240))
        # Вывод фона и текста
        screen.fill(BACKGROUND_COLOR)
        screen.blit(text, (central_point[0] - text.get_width() * 0.5,
                           central_point[1] - text.get_height() * 0.5))
        pygame.display.flip()
        # Задержка в милисекундах
        pygame.time.wait(100)
def execute(screen: pygame.surface.Surface):
    """
    Функция запускает меню игры на паузе на переданном экране. В
    зависимости от действий закрывает всю игру, либо продолжает дальше
    :param screen: Экран на котором надо отрисовывать менюв
    :return: Возвращает -1, если игру надо закрыть, None если нет
    """
    is_open = True
    clock = pygame.time.Clock()
    joystick = get_joystick() if check_any_joystick() else None

    # Смещение между UI элементами
    UI_MARGIN = 20
    # Фоновое изображение для всего экрана
    background_image = load_image("pause_menu_BG.png", "assets/UI")
    background_image = pygame.transform.scale(background_image,
                                              screen.get_size())
    # Фоновое игображение
    ui_background_image = load_image("pause_menu_UI_BG.png", "assets/UI")
    # Центральная координата всего меню на экране
    menu_top_left = (screen.get_width() * 0.5 -
                     ui_background_image.get_width() * 0.5,
                     screen.get_height() * 0.5 -
                     ui_background_image.get_height() * 0.5)

    # Создание UI элементов
    next_y = menu_top_left[1] + ui_background_image.get_width(
    ) * 0.5 - UI_MARGIN * 2.5
    button_continue = Button((screen.get_width() // 2, next_y),
                             "Продолжить",
                             32,
                             base_button_filename="button_1.png",
                             hover_button_filename="button_1_hover.png")

    next_y += button_continue.rect.width * 0.5 + UI_MARGIN
    button_exit = Button((screen.get_width() // 2, next_y),
                         "Выйти в меню",
                         32,
                         base_button_filename="button_1.png",
                         hover_button_filename="button_1_hover.png")

    # Добавление в группу
    UI_sprites = pygame.sprite.Group()
    UI_sprites.add(button_continue)
    UI_sprites.add(button_exit)

    # Изображение для курсора
    cursor_image = load_image("cursor.png", "assets/UI/icons")
    # координаты курсора
    cursor_x, cursor_y = screen.get_rect().center
    cursor_speed = 25  # скорость курсора (нужно если используется джойстик)

    # Цикл меню
    while is_open:
        # Переменная, становящайся True если было нажатие курсора
        # (предусмотрен как джойстик, так и обычная мышка)
        was_click = False

        # Обработка событий
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                is_open = False
                break

            if event.type == pygame.MOUSEBUTTONUP:
                if event.button == 1:
                    was_click = True

            if event.type == Button.PRESS_TYPE:
                # Текст нажатой кнопки
                # (гарантированно есть, т.к. устанавливается при инициализации)
                sender_text = event.dict["sender_text"]

                # Продолжить
                if sender_text == button_continue.text:
                    is_open = False
                    UI_sprites.empty()  # удаление всех спрайтов в группе
                    break

                # Выход
                if sender_text == button_exit.text:
                    return -1

        # Определение местоположения для курсора
        if joystick:
            axis_x, axis_y = joystick.get_axis(0), joystick.get_axis(1)
            cursor_x += cursor_speed * axis_x if abs(
                axis_x) >= JOYSTICK_SENSITIVITY else 0
            cursor_y += cursor_speed * axis_y if abs(
                axis_y) >= JOYSTICK_SENSITIVITY else 0
            # Проверка на нажатие
            was_click = joystick.get_button(CONTROLS["JOYSTICK_UI_CLICK"])
        else:
            cursor_x, cursor_y = pygame.mouse.get_pos()

        cursor_position = (cursor_x, cursor_y)
        # Обновляем все UI элементы
        UI_sprites.update(cursor_position, was_click)

        # Очистка экрана
        screen.fill((0, 0, 0))

        # Фоновое изображение окна
        screen.blit(background_image, (0, 0))
        # Фоновое изобраджение UI
        screen.blit(ui_background_image, menu_top_left)
        # Рисуем весь UI
        UI_sprites.draw(screen)

        # Рисуем курсор поверх всего
        screen.blit(cursor_image, cursor_position)
        pygame.display.flip()

        # Обновляем состояние джойстика
        joystick = get_joystick() if check_any_joystick() else None
        clock.tick(FPS)
Beispiel #9
0
def execute(screen: pygame.surface.Surface) -> int:
    """
    Функция запускает меню игры на паузе на переданном экране. В
    зависимости от действий закрывает всю игру, либо продолжает дальше
    :param screen: Экран на котором надо отрисовывать меню
    :return: Возвращает код. (1 - начать заного, -1 - закрыть игру, None - ничего)
    """
    is_open = True
    clock = pygame.time.Clock()
    joystick = get_joystick() if check_any_joystick() else None
    # Смещение между UI элементами
    margin = 20
    # Фоновое изображение для всего экрана
    background_image = AnimatedBackground(
        "pause_menu_BG_{0}.png", "assets/sprites/UI/backgrounds/pause_BG", 1,
        45, 25, screen.get_size())
    menu_width, menu_height = 280, 360
    # Фоновое игображение
    background_menu_image = scale_frame(
        load_image("assets/sprites/UI/backgrounds/pause_menu_UI_BG.png"),
        (menu_width, menu_height))
    # Центральная координата всего меню на экране
    menu_top_left = (screen.get_width() * 0.5 - menu_width * 0.5,
                     screen.get_height() * 0.25)
    # Группа со спрайтами интерфейса
    UI_sprites = pygame.sprite.Group()
    # Создание кнопок
    next_y = menu_top_left[1] + margin * 3.5  # позиция y следущего элемента
    titles = ("Продолжить", "Начать заново", "Выйти в меню"
              )  # заголовки кнопок
    for number in range(len(titles)):
        # Текущая кнопка
        button = Button((screen.get_width() // 2, next_y),
                        titles[number],
                        32,
                        base_button_filename="button_1.png",
                        hover_button_filename="button_1_hover.png")
        # Высчитывание следущей позиции по y со смещением
        next_y += button.rect.height + margin
        # Добавление в группу
        UI_sprites.add(button)
    # Изображение для курсора
    cursor_image = load_image("assets/sprites/UI/icons/cursor.png")
    # координаты курсора
    cursor_x, cursor_y = screen.get_rect().center
    cursor_speed = 40  # скорость курсора (нужно если используется джойстик)
    # Цикл меню
    while is_open:
        # Переменная, становящайся True если было нажатие курсора
        # (предусмотрен как джойстик, так и обычная мышка)
        was_click = False
        # Обработка событий
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                is_open = False
                break

            if event.type == pygame.MOUSEBUTTONUP:
                if event.button == 1:
                    was_click = True

            if event.type == pygame.KEYDOWN:
                if event.key == CONTROLS["KEYBOARD_PAUSE"]:
                    is_open = False
                    UI_sprites.empty()  # удаление всех спрайтов в группе
                    break

            if event.type == Button.PRESS_TYPE:
                # Текст нажатой кнопки
                # (гарантированно есть, т.к. устанавливается при инициализации)
                sender_text = event.dict["sender_text"]
                # Продолжить
                if sender_text == titles[0]:
                    is_open = False
                    UI_sprites.empty()  # удаление всех спрайтов в группе
                    break
                # Начать заного
                if sender_text == titles[1]:
                    return 1
                # Выход
                if sender_text == titles[-1]:
                    return -1
        # Определение местоположения для курсора
        if joystick:
            axis_x, axis_y = joystick.get_axis(0), joystick.get_axis(1)
            cursor_x += cursor_speed * axis_x if abs(
                axis_x) >= JOYSTICK_SENSITIVITY else 0
            cursor_y += cursor_speed * axis_y if abs(
                axis_y) >= JOYSTICK_SENSITIVITY else 0
            # Проверка на нажатие
            was_click = joystick.get_button(CONTROLS["JOYSTICK_UI_CLICK"])
        else:
            cursor_x, cursor_y = pygame.mouse.get_pos()
        cursor_position = cursor_x, cursor_y

        # Обновляем все UI элементы
        UI_sprites.update(cursor_position, was_click)
        # Очистка экрана
        screen.fill((0, 0, 0))
        # Фоновое изображение окна
        background_image.update()
        screen.blit(background_image.image, (0, 0))
        # Фоновое изобраджение UI
        screen.blit(background_menu_image, menu_top_left)
        # Рисуем весь UI
        UI_sprites.draw(screen)
        # Рисуем курсор поверх всего
        screen.blit(cursor_image, cursor_position)
        pygame.display.flip()
        # Обновляем состояние джойстика
        joystick = get_joystick() if check_any_joystick() else None
        clock.tick(FPS)
Beispiel #10
0
def execute(screen: pygame.surface.Surface,
            money: int,
            count_of_alive_assistants: int,
            is_win=False):
    """
    Функция запускает конечной экран (либо смерти, либо победы)
    :param screen: Экран на котором надо отрисовывать менюв
    :param is_win: Флаг, выиграл ли игрок
    :param money: Количество собранных игроком и асистентом денег
    :param count_of_alive_assistants: Количетсво всех живых осистентов к концу игры
    игры
    """
    is_open = True
    # Фоновое изображение для всего экрана
    if is_win:
        # Фоновая музыка при победе
        pygame.mixer.music.load("assets/audio/music/win_screen_BG.ogg")
        pygame.mixer.music.play(-1)
        animated_background = AnimatedBackground(
            "win_{0}.png", "assets/sprites/UI/backgrounds/triumph_screen", 1,
            8, 80, screen.get_size())
        # Картигка с заголовком победы
        title_you_win = load_image('assets/sprites/UI/you_win.png')
        you_win_rect = title_you_win.get_rect()
        you_win_rect.center = screen.get_rect().centerx, int(
            screen.get_rect().centery * 0.7)
    else:
        # Фоновая музыка при проигрыше
        pygame.mixer.music.load("assets/audio/music/fail_screen_BG.mp3")
        pygame.mixer.music.play(-1)
        # Высчитывание размера для фона и сам фон
        size = screen.get_width() // 3, screen.get_height() // 3
        animated_background = AnimatedBackground(
            "death_{0}.png",
            "assets/sprites/UI/backgrounds/fail_screen",
            1,
            23,
            140,
            size,
            scale_2n=True)
    # Лого игры
    logo = LogoImage((screen.get_width() * 0.5, screen.get_height() * 0.1))
    # Изображение курсора
    cursor_image = load_image("assets/sprites/UI/icons/cursor.png")
    # Получение джойстика (если есть) и определение начальной позиции курсора
    if check_any_joystick():
        joystick = get_joystick()
        cursor_x, cursor_y = screen.get_rect().center
    else:
        joystick = None
        # Т.к. джойстика нет позиция будет сразу переопределна далее,
        # поэтому тут начальная позиция не задаётся
        cursor_x, cursor_y = 0, 0
    # Т.к. игрок завершил игру, то файл с сохранением будет перезаписан
    if os.path.isfile("data/save.txt"):
        with open('data/save.txt', 'r+', encoding="utf-8") as file:
            file.truncate(0)
    # Кортеж с текстом который надо вывести (каждый элемент на новой строке)
    texts = (f"Деньги собранные игроком вместе с асистентом: {money}",
             f"Количество живых асистентов: {count_of_alive_assistants}")
    # Шрифт для поверхностей ниже
    title_font = load_game_font(64)
    # Поверхности с одним и тем же текстом, но разный цвет делает крассивый эффект
    text_surfaces_yellow = [
        title_font.render(part.strip(), True, (255, 184, 50)) for part in texts
    ]
    text_surfaces_red = [
        title_font.render(part.strip(), True, (179, 64, 16)) for part in texts
    ]
    # Смещение между наложенными поверхностями для красивого эффекта
    surfaces_offset = 3
    margin = title_font.get_height() * 0.9  # отступ между двумя поверхностями
    # События, которые активируют закрытие экрана с концном
    QUITING_EVENTS = (
        pygame.QUIT,
        pygame.MOUSEBUTTONUP,
        pygame.KEYDOWN,
    )
    # Цикл меню
    while is_open:
        # Обработка событий
        for event in pygame.event.get():
            if event.type in QUITING_EVENTS:
                is_open = False
                break
        # Обновление позиции курсора
        if joystick is not None:
            # Проверка на выход
            if joystick.get_button(CONTROLS["JOYSTICK_UI_CLICK"]):
                break
            # Значение осей на левом стике
            axis_x, axis_y = joystick.get_axis(0), joystick.get_axis(1)
            # Перемещение курсора при движении оси
            if abs(axis_x) >= JOYSTICK_SENSITIVITY:
                cursor_x += JOYSTICK_CURSOR_SPEED * axis_x
            if abs(axis_y) >= JOYSTICK_SENSITIVITY:
                cursor_y += JOYSTICK_CURSOR_SPEED * axis_y
        else:
            cursor_x, cursor_y = pygame.mouse.get_pos()
        # На экране проигрыша есть фон, которого нет на экране победы
        if not is_win:
            screen.fill((31, 30, 36))
        # Вывод текущего кадра фонового изображения
        animated_background.update()
        screen.blit(
            animated_background.image,
            animated_background.image.get_rect(
                center=screen.get_rect().center))
        # Вывод картинки победного заголовка, если игрок выиграл
        if is_win:
            # Анализатор может ругаться, но если is_win истина, то
            # переменные 100% объявлены выше
            screen.blit(title_you_win, you_win_rect)
        # следущая позиция по y (будет нужно при вычислении смещения)
        next_y = 20
        # Вывод красного текста
        for text_surface in text_surfaces_red:
            y_pos = screen.get_height() * 0.6 + next_y
            screen.blit(
                text_surface,
                text_surface.get_rect(midtop=(screen.get_rect().centerx +
                                              surfaces_offset,
                                              y_pos + surfaces_offset)))
            next_y += margin
        next_y = 20
        # Вывод жёлтого текста
        for text_surface in text_surfaces_yellow:
            y_pos = screen.get_height() * 0.6 + next_y
            screen.blit(
                text_surface,
                text_surface.get_rect(midtop=(screen.get_rect().centerx,
                                              y_pos)))
            next_y += margin
        # Вывод логотипа игры
        screen.blit(logo.image, logo.rect.topleft)
        # Вывод изображения курсора
        screen.blit(cursor_image, (cursor_x, cursor_y))

        # Обновление состояния джойстика
        joystick = get_joystick() if check_any_joystick() else None
        pygame.display.flip()
Beispiel #11
0
def execute(screen: pygame.surface.Surface, is_win=False):
    """
    Функция запускает конечной экран (либо смерти, либо победы)
    :param screen: Экран на котором надо отрисовывать менюв
    :param is_win: Флаг, выиграл ли игрок
    """

    is_open = True
    clock = pygame.time.Clock()
    joystick = get_joystick() if check_any_joystick() else None

    # Фоновое изображение для всего экрана
    if not is_win:
        animated_background = AnimatedBackground("death_{0}.png", 1, 23, 60,
                                                 screen.get_size())
    else:
        # Фоновая музыка для победителя
        pygame.mixer.music.load(
            concat_two_file_paths("assets/audio", "win_screen_BG.ogg"))
        pygame.mixer.music.play(-1)
        animated_background = AnimatedBackground("win_{0}.png", 1, 8, 60,
                                                 screen.get_size())

    # Лого игры
    logo = LogoImage((screen.get_width() * 0.5, screen.get_height() * 0.1))

    # Кнопка возвращения в меню
    button_exit = Button((screen.get_width() // 2, screen.get_height() * 0.9),
                         "Вернутся в меню",
                         32,
                         base_button_filename="button_1.png",
                         hover_button_filename="button_1_hover.png")

    # Добавление в группу
    UI_sprites = pygame.sprite.Group()
    UI_sprites.add(logo)
    UI_sprites.add(button_exit)

    # Изображение для курсора
    cursor_image = load_image("cursor.png", "assets/UI/icons")
    # координаты курсора
    cursor_x, cursor_y = screen.get_rect().center
    cursor_speed = 15  # скорость курсора (нужно если используется джойстик)

    # Т.к. игрок завершил игру, то файл с сохранением будет перезаписан
    if os.path.isfile("data/save.txt"):
        with open('data/save.txt', 'r+', encoding="utf-8") as file:
            file.truncate(0)

    # Цикл меню
    while is_open:
        # Переменная, становящайся True если было нажатие курсора
        # (предусмотрен как джойстик, так и обычная мышка)
        was_click = False

        # Обработка событий
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                is_open = False
                break

            if event.type == pygame.MOUSEBUTTONUP:
                if event.button == 1:
                    was_click = True

            if event.type == Button.PRESS_TYPE:
                # Текст нажатой кнопки
                # (гарантированно есть, т.к. устанавливается при инициализации)
                sender_text = event.dict["sender_text"]

                # Выход
                if sender_text == button_exit.text:
                    return

        # Определение местоположения для курсора
        if joystick:
            axis_x, axis_y = joystick.get_axis(0), joystick.get_axis(1)
            cursor_x += cursor_speed * axis_x if abs(
                axis_x) >= JOYSTICK_SENSITIVITY else 0
            cursor_y += cursor_speed * axis_y if abs(
                axis_y) >= JOYSTICK_SENSITIVITY else 0
            # Проверка на нажатие
            was_click = joystick.get_button(CONTROLS["JOYSTICK_UI_CLICK"])
        else:
            cursor_x, cursor_y = pygame.mouse.get_pos()

        cursor_position = (cursor_x, cursor_y)
        # Обновляем все UI элементы
        UI_sprites.update(cursor_position, was_click)

        # Очистка экрана
        screen.fill((0, 0, 0))

        animated_background.update()
        # Вывод текущего кадра фонового изображения
        screen.blit(animated_background.image, (0, 0))

        # Рисуем весь UI
        UI_sprites.draw(screen)

        # Рисуем курсор поверх всего
        screen.blit(cursor_image, cursor_position)
        pygame.display.flip()

        # Обновляем состояние джойстика
        joystick = get_joystick() if check_any_joystick() else None
        clock.tick(FPS)
Beispiel #12
0
def game(displaysurf: pg.surface.Surface, clock: pg.time.Clock, diff: str,
         diff_color: Tuple[int, int, int]) -> int:
    """게임의 메인 로직을 실행한다.

    Args:
        displaysurf: init 함수에 의해 반환된 최상위 Surface
        clock: init 함수에 의해 반환된 Clock
        diff: prompt_difficulty 함수에 의해 반환된 난이도
        diff_color: prompt_difficulty 함수에 의해 반환된 난이도에 해당하는 색상

    Returns:
        게임 결과(점수)

    """

    screenrect = displaysurf.get_rect()  # 게임 영역 설정

    groupdict: Dict[str, pg.sprite.Group] = dict()  # 그룹 불러오기
    groupdict = {
        'bullet': pg.sprite.Group(),
        'player': pg.sprite.Group(),
        'enemy': pg.sprite.Group(),
        'danmaku': pg.sprite.Group()
    }

    spritedict: Dict[str, Element] = dict()

    parser = Parser(screenrect, groupdict, spritedict)  # 패턴 구문분석

    spritedict['player'] = parser.load('assets/player.json')
    groupdict['player'].add(spritedict['player'])  # 플레이어 추가

    loadeddict = loadfiles(diff)  # 패턴 파일 로드
    sounddict = loadsounds()

    _frame: int = 0
    frame: int = 0
    score: int = ct.INITIALSCORE
    limittime: float = ct.LIMITTIME
    onon: int = 0  # 변수 결정

    pg.mixer.Sound.play(sounddict['bgm'])

    while True:  # 게임 구동기
        _frame += 1  # 시간 증가
        frame += 1

        if frame == limittime // 1 and onon == 0:  # 게임 중 적 생성 시간일 때
            enemychoose(groupdict['enemy'], parser, loadeddict)  # 적 생성
            frame = 0  # 적 생성 시간 초기화
            if limittime > ct.OVERLIMIT:
                limittime -= ct.LIMITREDUCE  # 적 생성 주기 단축
            else:
                onon = 1  # 게임 종료 시간

        if onon == 1:  # 게임 끝
            if frame == ct.OVERTIME:
                return score

        for event in pg.event.get():
            groupdict['player'].update(event=event)  # 객체 위치 이동
            if event.type == pg.QUIT:  # 종료 버튼
                pg.quit()
                sys.exit()

        displaysurf.fill(ct.BLACK)  # 배경 색
        if pg.sprite.groupcollide(groupdict['player'], groupdict['danmaku'],
                                  False, False):
            score -= 1  # 부딫혔을 때 충돌 카운트 +1
            pg.mixer.Sound.play(sounddict['gothit'])

        # 쏜 총이 적 맞았을 때 적 kill
        pg.sprite.groupcollide(groupdict['bullet'], groupdict['enemy'], False,
                               True)

        enemyn = len(groupdict['enemy'])
        for key in groupdict:
            groupdict[key].update()  # 모든 객체 위치 업데이트
            groupdict[key].draw(displaysurf)
        # 적이 자연적으로 죽을 경우 페널티
        score -= ct.PENALTY * (enemyn - len(groupdict['enemy']))

        write_text(displaysurf, 60, (20, 20), f"{score}", ct.WHITE)
        write_text_rt(displaysurf, 60, (ct.WIDTH - 20, 20), diff, diff_color)

        pg.display.update()
        clock.tick(ct.FPS)  # 시간 업데이트
Beispiel #13
0
def game_over_menu(surface: pygame.surface.Surface, score: int):
    """
    Displays the game over menu
    """

    menu_rect = pygame.rect.Rect(
        (constants.window_width // 4, constants.window_width // 4),
        (constants.window_width // 2, constants.window_height // 2))
    menu_rect.center = (constants.window_width // 2,
                        constants.window_height // 2)
    over_background = (50, 50, 50)
    over_foreground = (200, 200, 200)

    gui_manager = pygame_gui.UIManager(
        (constants.window_width, constants.window_height),
        'game_over_theme.json')
    clock = pygame.time.Clock()
    font = pygame.font.Font("ARCADECLASSIC.TTF",
                            constants.generalise_height(75))
    over_img = font.render("game over", True, over_foreground, over_background)
    over_rect = over_img.get_rect()
    over_rect.center = (constants.generalise_width(640),
                        constants.generalise_height(292))

    score_font = pygame.font.Font("ARCADECLASSIC.TTF",
                                  constants.generalise_height(48))
    string = "Score is " + str(score)
    score_img = score_font.render(string, True, over_foreground,
                                  over_background)
    score_rect = score_img.get_rect()
    score_rect.center = (constants.generalise_width(549 + 82),
                         constants.generalise_height(370))

    restart_button_rect = pygame.Rect(
        (constants.generalise_width(549), constants.generalise_height(409)),
        (constants.generalise_width(164), constants.generalise_height(41)))
    quit_button_rect = pygame.Rect(
        (constants.generalise_width(549), constants.generalise_height(468)),
        (constants.generalise_width(164), constants.generalise_height(41)))

    restart_button = pygame_gui.elements.UIButton(
        relative_rect=restart_button_rect, text="restart", manager=gui_manager)
    quit_button = pygame_gui.elements.UIButton(relative_rect=quit_button_rect,
                                               text="Exit to menu",
                                               manager=gui_manager)

    is_paused = True
    while is_paused:
        dt = clock.tick(60) / 1000.0
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return GAME_STATES.QUIT
            if event.type == pygame.USEREVENT:
                if event.user_type == pygame_gui.UI_BUTTON_PRESSED:
                    if event.ui_element == quit_button:
                        return GAME_STATES.MAIN_MENU
                    if event.ui_element == restart_button:
                        return GAME_STATES.IN_GAME
            gui_manager.process_events(event)
        gui_manager.update(dt)

        surface.fill(over_background, menu_rect)
        surface.blit(over_img, over_rect)
        surface.blit(score_img, score_rect)
        gui_manager.draw_ui(surface)

        pygame.display.update(menu_rect)
Beispiel #14
0
def ingame(surface: pygame.surface.Surface):
    """
    Create the asteroids
    Initialise necessary variables
    """
    asteroid_count = 8
    clock = pygame.time.Clock()
    font = pygame.font.Font("ARCADECLASSIC.TTF", 48)
    score = 0
    score_img = font.render(str(score), True, (200, 200, 200),
                            background_color)
    score_rect = score_img.get_rect()
    score_rect.topright = (constants.window_width - 30, 30)
    asteroids_group = pygame.sprite.Group()
    for i in range(0, asteroid_count):
        tmp_start_vel = [0, 0]
        tmp_start_pos = [0, 0]
        if numpy.random.random() < 0.5:
            tmp_start_pos = [
                -constants.asteroid_radius,
                constants.window_height * (0.1 + numpy.random.random() * 0.8)
            ]
            tmp_start_vel = [constants.asteroid_start_vel, 0]
        else:
            tmp_start_pos = [
                constants.window_width + constants.asteroid_radius,
                constants.window_height * numpy.random.random()
            ]
            tmp_start_vel = [-constants.asteroid_start_vel, 0]
        tmp = asteroid.asteroid(
            asteroid_count, numpy.array(tmp_start_pos),
            constants.generalise_height(constants.asteroid_radius),
            numpy.array(tmp_start_vel))
        asteroids_group.add(tmp)
    player = rocket.rocket()
    bullets = []
    parent = None
    parent_qual = 0
    last_best_check_tick = -1000

    is_running = True
    while is_running:
        """
        Calculate the time taken for the previous frame and cap FPS to 60
        """
        dt = clock.tick(60) / 1000.0
        """
        Handle input and quit events
        """
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return GAME_STATES.QUIT
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_ESCAPE:
                    ret = pause_menu(surface)
                    if ret != GAME_STATES.IN_GAME:
                        return ret
        """
        If the player is dead, display the game over menu
        """
        if player.status == rocket.ROCKET_STATUS.DEAD:
            return game_over_menu(surface, score)
        """
        Update positions and velocities of bullets, asteroids and player
        """
        asteroids_group.update(asteroids_group, player, dt, bullets)
        player.update(asteroids_group, dt, bullets)
        for i in range(0, len(bullets)):
            bullets[i].update(dt)
        """
        Remove destroyed asteroids,
        and create new ones if necessary
        """
        to_be_removed = []
        if parent is None:
            parent = asteroids_group.sprites()[0]
            parent_qual = calc_quality(parent)
        for a in asteroids_group:
            qual = calc_quality(a)
            if qual > parent_qual:
                parent = a
                parent_qual = qual
        for ast in asteroids_group:
            if ast.status == asteroid.ASTEROID_STATUS.DESTROYED:
                to_be_removed.append(ast)
                if ast.destroyed_by_player:
                    """
                    Increment the score and update the score display
                    if an asteroid has been destroyed by the player
                    """
                    score += 1
                    score_img = font.render(str(score), True, (200, 200, 200),
                                            background_color)
                    score_rect = score_img.get_rect()
                    score_rect.topright = (constants.window_width - 30, 30)
        for r in to_be_removed:
            asteroids_group.remove(r)
            tmp_start_vel = [0, 0]
            tmp_start_pos = [0, 0]
            if numpy.random.random() < 0.5:
                tmp_start_pos = [
                    0 - constants.asteroid_radius, constants.window_height *
                    (0.1 + numpy.random.random() * 0.8)
                ]
                tmp_start_vel = [constants.asteroid_start_vel, 0]
            else:
                tmp_start_pos = [
                    constants.window_width + constants.asteroid_radius,
                    constants.window_height * numpy.random.random()
                ]
                tmp_start_vel = [-constants.asteroid_start_vel, 0]
            tmp = asteroid.asteroid(
                asteroid_count, numpy.array(tmp_start_pos),
                constants.generalise_height(constants.asteroid_radius),
                numpy.array(tmp_start_vel))
            tmp.evolve_from(parent)
            asteroids_group.add(tmp)
        to_be_removed = []
        """
        Clear the background and draw the player, asteroids
        and the bullets
        """
        surface.fill(background_color)
        for i in range(0, len(bullets)):
            pos = bullets[i].position
            if pos[0] < 0 or pos[0] > constants.window_width or pos[1] < 0 or\
               pos[1] > constants.window_height:
                to_be_removed.append(bullets[i])
            bullets[i].draw(surface)
        for i in to_be_removed:
            bullets.remove(i)
        asteroids_group.draw(surface)
        surface.blit(player.image, player.rect)
        surface.blit(score_img, score_rect)

        pygame.display.update()
Beispiel #15
0
def pause_menu(surface: pygame.surface.Surface):
    """
    Displays the pause menu
    """
    menu_rect = pygame.rect.Rect(
        (constants.window_width // 4, constants.window_width // 4),
        (constants.window_width // 2, constants.window_height // 2))
    menu_rect.center = (constants.window_width // 2,
                        constants.window_height // 2)
    paused_background = (50, 50, 50)
    paused_foreground = (200, 200, 200)

    gui_manager = pygame_gui.UIManager(
        (constants.window_width, constants.window_height),
        'pause_menu_theme.json')
    clock = pygame.time.Clock()
    font = pygame.font.Font("ARCADECLASSIC.TTF",
                            constants.generalise_height(75))
    pause_img = font.render("game paused", True, paused_foreground,
                            paused_background)
    pause_rect = pause_img.get_rect()
    pause_rect.center = (constants.generalise_width(640),
                         constants.generalise_height(292))

    resume_button_rect = pygame.Rect(
        (constants.generalise_width(549), constants.generalise_height(350)),
        (constants.generalise_width(164), constants.generalise_height(41)))
    quit_button_rect = pygame.Rect(
        (constants.generalise_width(549), constants.generalise_height(409)),
        (constants.generalise_width(164), constants.generalise_height(41)))
    menu_button_rect = pygame.Rect(
        (constants.generalise_width(549), constants.generalise_height(468)),
        (constants.generalise_width(164), constants.generalise_height(41)))

    resume_button = pygame_gui.elements.UIButton(
        relative_rect=resume_button_rect, text="Resume", manager=gui_manager)
    quit_button = pygame_gui.elements.UIButton(relative_rect=quit_button_rect,
                                               text="Quit",
                                               manager=gui_manager)
    menu_button = pygame_gui.elements.UIButton(relative_rect=menu_button_rect,
                                               text="Exit to menu",
                                               manager=gui_manager)

    is_paused = True
    while is_paused:
        dt = clock.tick(60) / 1000.0
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return GAME_STATES.QUIT
            if event.type == pygame.USEREVENT:
                if event.user_type == pygame_gui.UI_BUTTON_PRESSED:
                    if event.ui_element == quit_button:
                        return GAME_STATES.QUIT
                    if event.ui_element == resume_button:
                        return GAME_STATES.IN_GAME
                    if event.ui_element == menu_button:
                        return GAME_STATES.MAIN_MENU

            gui_manager.process_events(event)

        gui_manager.update(dt)

        surface.fill(paused_background, menu_rect)
        surface.blit(pause_img, pause_rect)
        gui_manager.draw_ui(surface)

        pygame.display.update(menu_rect)
Beispiel #16
0
def execute(screen: pygame.surface.Surface) -> int:
    """
    Функция запускает главное меню игры на переданном экране. В
    зависимости от действий возвращает свой код
    0 - была нажата кнопка выйти
    1 - была нажата кнопка играть
    :param screen: Экран на котором надо отрисовывать менюв
    :return: Код
    """
    is_open = True
    clock = pygame.time.Clock()
    joystick = get_joystick() if check_any_joystick() else None

    # Смещение между UI элементами
    UI_MARGIN = 55

    # Создание UI элементов
    game_logo = LogoImage(
        (screen.get_width() // 2, screen.get_height() // 6 - UI_MARGIN))
    next_y = game_logo.rect.y + game_logo.rect.height + UI_MARGIN * 2

    button_play = Button((screen.get_width() // 2, next_y), "Играть", 32)
    next_y = button_play.rect.y + button_play.rect.height + UI_MARGIN

    button_controls = Button((screen.get_width() // 2, next_y), "Управление",
                             32)
    next_y = button_controls.rect.y + button_controls.rect.height + UI_MARGIN

    button_about = Button((screen.get_width() // 2, next_y), "Об игре", 32)
    next_y = button_about.rect.y + button_about.rect.height + UI_MARGIN

    button_authors = Button((screen.get_width() // 2, next_y), "Авторы", 32)
    next_y = button_authors.rect.y + button_authors.rect.height + UI_MARGIN

    button_exit = Button((screen.get_width() // 2, next_y), "Выйти", 32)

    # Добавление в группу
    UI_sprites = pygame.sprite.Group()
    UI_sprites.add(game_logo)
    UI_sprites.add(button_play)
    UI_sprites.add(button_controls)
    UI_sprites.add(button_about)
    UI_sprites.add(button_authors)
    UI_sprites.add(button_exit)

    # Текущие диалог (может появлятся при нажатии кнопок)
    current_message_box = None

    # Фоновое изоюражение
    background_image = load_image("main_menu_BG.png", "assets/UI")
    # Меняем размер картинки в зависимости от размера экрана
    background_image = pygame.transform.scale(
        background_image, (screen.get_width(), screen.get_height()))

    # Делаем курсор мыши невидимым и загружаем вместо него своё изображение
    pygame.mouse.set_visible(False)
    cursor_image = load_image("cursor.png", "assets/UI/icons")
    # координаты курсора
    cursor_x, cursor_y = screen.get_width() * 0.5, screen.get_height() * 0.1
    cursor_speed = 30  # скорость курсора (нужно если используется джойстик)

    # Фоновая музыка
    pygame.mixer.music.load(
        concat_two_file_paths("assets/audio", "main_menu.ogg"))
    # Воспроизведение музыки вечно
    pygame.mixer.music.play(-1)
    # Установка громкости
    pygame.mixer.music.set_volume(DEFAULT_MUSIC_VOLUME)

    # Переменная, становящайся True если было нажатие курсора
    # (предусмотрен как джойстик, так и обычная мышка)
    was_click = False

    # Цикл окна
    while is_open:
        # Обработка событий
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                is_open = False
                break

            if event.type == pygame.MOUSEBUTTONUP:
                if event.button == 1:
                    was_click = True

            if event.type == Button.PRESS_TYPE:
                # Текст нажатой кнопки
                # (гарантированно есть, т.к. устанавливается при инициализации)
                sender_text = event.dict["sender_text"]

                # Управление
                if sender_text == button_controls.text:
                    text = str("Базовое управление:\n" +
                               "На клавиатуре: WASD - двигаться; Q - рывок\n" +
                               "На джойстике: PADS - двигаться; R1 - рывок\n")
                    current_message_box = MessageBox(
                        text, 30,
                        (screen.get_width() * 0.5, screen.get_height() * 0.5))
                    continue

                # Об игре
                if sender_text == button_about.text:
                    text = str("Игра жанра Rogulite, в \n"
                               "которой надо пройти \n" +
                               "сквозь подземелье, заполненное врагами.\n"
                               "Желаем удачи\n")
                    current_message_box = MessageBox(
                        text, 30,
                        (screen.get_width() * 0.5, screen.get_height() * 0.5))
                    continue

                # Авторы
                if sender_text == button_authors.text:
                    text = str("Никита Сошнев (Nik4ant)\n"
                               "Максим Рудаков (Massering)")
                    current_message_box = MessageBox(
                        text, 30,
                        (screen.get_width() * 0.5, screen.get_height() * 0.5))
                    continue

                # Музыка затухает (1 секунду), т.к. главный экран закроется
                pygame.mixer.music.fadeout(1000)

                # Проверяем какая кнопка была нажата
                if sender_text == button_play.text:
                    return 1
                elif sender_text == button_exit.text:
                    return 0

        # Определение местоположения для курсора
        if joystick:
            axis_x, axis_y = joystick.get_axis(0), joystick.get_axis(1)
            cursor_x += cursor_speed * axis_x if abs(
                axis_x) >= JOYSTICK_SENSITIVITY else 0
            cursor_y += cursor_speed * axis_y if abs(
                axis_y) >= JOYSTICK_SENSITIVITY else 0
            # Проверка на нажатие
            was_click = joystick.get_button(CONTROLS["JOYSTICK_UI_CLICK"])
        else:
            cursor_x, cursor_y = pygame.mouse.get_pos()

        cursor_position = (cursor_x, cursor_y)
        # Обновляем все UI элементы
        UI_sprites.update(cursor_position, was_click)

        # Очистка экрана
        screen.fill((0, 0, 0))

        # Фоновое изобраджение
        screen.blit(background_image, (0, 0))
        # Рисуем весь UI
        UI_sprites.draw(screen)
        # Если есть диалог, то его тоже обновляем и рисуем
        if current_message_box:
            current_message_box.update(was_click)
            if current_message_box.need_to_draw:
                current_message_box.draw(screen)

        # Рисуем курсор поверх всего
        screen.blit(cursor_image, cursor_position)
        pygame.display.flip()

        # Обновляем состояние джойстика
        joystick = get_joystick() if check_any_joystick() else None
        was_click = False
        clock.tick(FPS)