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))))
コード例 #2
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()
コード例 #3
0
    def __init__(self,
                 relative_rect: pygame.Rect,
                 image_surface: pygame.surface.Surface,
                 manager: IUIManagerInterface,
                 container: Union[IContainerLikeInterface, None] = None,
                 parent_element: UIElement = None,
                 object_id: Union[ObjectID, str, None] = None,
                 anchors: Dict[str, str] = None,
                 visible: int = 1):

        super().__init__(relative_rect,
                         manager,
                         container,
                         starting_height=1,
                         layer_thickness=1,
                         anchors=anchors,
                         visible=visible)

        self._create_valid_ids(container=container,
                               parent_element=parent_element,
                               object_id=object_id,
                               element_id='image')

        self.original_image = None
        # GUI images must support an alpha channel & must have their alpha channel pre-multiplied
        # with their colours.
        image_surface = premul_alpha_surface(image_surface.convert_alpha())
        if (image_surface.get_width() != self.rect.width
                or image_surface.get_height() != self.rect.height):
            self.original_image = image_surface
            self.set_image(
                pygame.transform.smoothscale(self.original_image,
                                             self.rect.size))
        else:
            self.set_image(image_surface)
コード例 #4
0
 def __init__(self, screen: pygame.surface.Surface, text: str, height: int):
     super().__init__()
     # Изображение
     self.image = self.font.render(text, True,
                                   (255, 244, 79)).convert_alpha()
     self.rect = self.image.get_rect()
     self.rect.center = screen.get_width() // 2, int(height)
     # Последнее время столкновения
     self.last_collide_time = -self.DRAWING_TIME
コード例 #5
0
ファイル: sprite.py プロジェクト: 1m188/snake
 def draw(self, screen: pygame.surface.Surface):
     width = screen.get_width()
     height = screen.get_height()
     for i in range(config.vertInrNum):
         pygame.draw.line(screen, (0, 0, 0), (0, i * config.vertInr),
                          (width, i * config.vertInr))
     for i in range(1, config.horzInrNum):
         pygame.draw.line(screen, (0, 0, 0), (i * config.horzInr, 0),
                          (i * config.horzInr, height))
コード例 #6
0
ファイル: main.py プロジェクト: Boris-Shatuev/solor-atum
 def __init__(self, surf: pygame.surface.Surface, border: int, border_radius: int, progress: int, max_progress=100):
     self.color = (243, 246, 250)
     self.border_radius = border_radius
     self.border_color = (0, 22, 87)
     self.x = 0
     self.y = 0
     self.height = surf.get_height()
     self.width = surf.get_width()
     self.surf = surf
     self.border_width = border
     self.progress = progress
     self.max_progress = max_progress
     self.bg_color = (0, 0, 34)
コード例 #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)
コード例 #8
0
    def draw_colourless_rounded_rectangle(
            large_corner_radius: int,
            large_shape_surface: pygame.surface.Surface,
            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 corner_offset: Offsets the corners, used to help avoid overlaps that look bad.

        """
        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)
コード例 #9
0
def cut_sheet(sheet: pygame.surface.Surface,
              columns: int,
              rows: int,
              size=(TILE_SIZE, TILE_SIZE)) -> list:
    """
    Функция нарезает spritesheet на кадры по переданным пвраметрам
    :param sheet: Поверхность с загруженным spritesheet'ом
    :param columns: Количество колонок для нарезки
    :param rows: Количество строк для нарезки
    :param size: Размер к которому маштабируется каждый кадр
    (по умолчанию размер тайла)
    :return: Вложенный список с кадрами
    """
    # Ширина и длинна по которой будет делаться вырезка
    cut_size = (sheet.get_width() // columns, sheet.get_height() // rows)
    # Нарезанные кадры
    frames = [[
        cut_sprite(sheet, i, j, size, cut_size) for i in range(columns)
    ] for j in range(rows)]
    return frames
コード例 #10
0
def render(surface: pygame.surface.Surface, dialog: Dialog,
           progress: int) -> int:
    """renders the given dialog to the given surface"""
    portrait_border = pygame.image.load('art/portraits/portrait_border.png')
    sentence_border = pygame.image.load('art/portraits/sentence_border.png')
    sentence = dialog.sentences[progress]
    portrait = sentence.speaker.portrait
    pos_y = surface.get_height() - portrait.get_height()

    rect = pygame.Rect(0, pos_y, surface.get_width(), portrait.get_height())

    text_surf = font.render(sentence.text, False, sentence.speaker.color)
    portrait_border.set_colorkey((255, 0, 255))
    sentence_border.set_colorkey((255, 0, 255))

    # TODO: make color adjustable
    pygame.draw.rect(surface, pygame.color.Color(10, 10, 10), rect)
    surface.blit(portrait, (0, pos_y))
    surface.blit(portrait_border, (0, pos_y))
    surface.blit(text_surf, (portrait.get_width() + padding, pos_y + padding))
    surface.blit(sentence_border, (portrait.get_width(), pos_y))
コード例 #11
0
def execute(screen: pygame.surface.Surface) -> int:
    """
    Функция запускает главное меню игры на переданном экране. В
    зависимости от действий возвращает свой код\n
    -1 - была нажата кнопка выйти\n
    1 - была нажата кнопка играть\n
    2 - была нажата кнопка туториал\n
    3 - была нажата кнопка найстроки\n
    :param screen: Экран на котором надо отрисовывать менюв
    :return: Код
    """
    is_open = True
    clock = pygame.time.Clock()
    joystick = get_joystick() if check_any_joystick() else None

    # Создание UI элементов
    # Кнопки
    BUTTONS_MARGIN = 55

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

    button_tutorial = Button((screen.get_width() // 2, next_y), "Обучение", 32)
    next_y = button_tutorial.rect.y + button_tutorial.rect.height + BUTTONS_MARGIN

    button_settings = Button((screen.get_width() // 2, next_y), "Настройки", 32)
    next_y = button_settings.rect.y + button_settings.rect.height + BUTTONS_MARGIN

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

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

    # Фоновое изоюражение
    background_image = load_image("main_menu_BG.png", "assets/UI")
    # Меняем размер картинки в зависимости от размера экрана
    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(os.path.join("assets/audio", "main_menu.ogg"))
    # Воспроизведение музыки вечно
    pygame.mixer.music.play(-1)
    # Установка громкости
    pygame.mixer.music.set_volume(DEFAULT_MUSIC_VOLUME)

    # Цикл окна
    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:
                # Музыка затухает (1 секунду), т.к. главный экран закроется
                pygame.mixer.music.fadeout(1000)

                # Текст нажатой кнопки
                # (гарантированно есть, т.к. устанавливается при инициализации)
                sender_text = event.dict["sender_text"]
                # Проверяем какая кнопка была нажата
                if sender_text == button_play.text:
                    return 1
                elif sender_text == button_tutorial.text:
                    return 2
                elif sender_text == button_settings.text:
                    # TODO: либо вызывать меню с настройками явно (но это потом)
                    return 3
                elif 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.blit(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)
コード例 #12
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)
コード例 #13
0
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)
コード例 #14
0
ファイル: game_menu.py プロジェクト: Nik4ant/pygame_project
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)
コード例 #15
0
def execute(screen: pygame.surface.Surface) -> int:
    """
    Функция запускает главное меню игры на переданном экране. В
    зависимости от действий возвращает свой код, описанный в main.py
    :param screen: Экран, на котором надо отрисовывать меню
    :return: Код
    """
    is_open = True
    clock = pygame.time.Clock()
    joystick = get_joystick() if check_any_joystick() else None

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

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

    button_play = Button((screen_center, next_y), "Играть", 32)
    next_y = button_play.rect.y + button_play.rect.height + button_margin
    # Если файла сохранения нет (т.е. игрок играет в первый раз), то эта кнопка
    # выделяется caps lock'ом (выделяются кнопки "управление" и "об игре")
    button_controls = Button(
        (screen_center, next_y),
        "Управление" if exists('data/save.txt') else "УПРАВЛЕНИЕ", 32)
    next_y = button_controls.rect.y + button_controls.rect.height + button_margin

    button_about = Button((screen_center, next_y),
                          "Об игре" if exists('data/save.txt') else "ОБ ИГРЕ",
                          32)
    next_y = button_about.rect.y + button_about.rect.height + button_margin

    button_exit = Button((screen_center, 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_exit)
    # Текущие диалог (может появлятся при нажатии кнопок)
    current_message_box = None
    # Текст появляющийся в сообщении при нажатии на кнопку "управление"
    control_text = """На клавиатуре: 
    WASD/Стрелки направлений - Двигаться
    Shift - Рывок
    1-5 - Заклинания атаки
    Space - Заклинание телепорта

    На джойстике PS4 (проводном): 
    PADS - Двигаться
    R1 - Рывок
    Заклинания см. на иконках
    """
    control_message_box = MessageBox(
        control_text, 32, (screen_center, screen.get_height() * 0.5))
    # Текст появляющийся в сообщении при нажатии на кнопку "об игре"
    about_text = """
    Pixelarious
Игра была создана как проект на тему PyGame для Яндекс Лицея.
Игра жанра Rogulite, поэтому смерть в игре перманентна.
Чтобы победить, надо пройти 10 уровней подземелья.
Чтобы убивать врагов, нужно использовать заклинания (см. управление).
Играть можно как на клавиутуре, так и на проводном джойстике от PS4.
Управление показывается внутри игры на главном окне при нажатии на кнопку "Управление". 
Его РЕКОМЕНДУЕТСЯ прочитать перед началом игры.
Ещё ОБЯЗАТЕЛЬНО посмотрите ОСОБЕННОСТИ заклинаний, НАВЕДЯ НА ИКОНКУ заклинания внизу.

Удачи в прохождении!
"""
    about_message_box = MessageBox(about_text, 32,
                                   (screen_center, screen.get_height() * 0.5))
    # Фоновое изоюражение
    background_image = load_image(
        "assets/sprites/UI/backgrounds/main_menu_BG.png")
    # Меняем размер картинки в зависимости от размера экрана
    background_image = pygame.transform.scale(background_image,
                                              screen.get_size())
    # Делаем курсор мыши невидимым и загружаем вместо него своё изображение
    pygame.mouse.set_visible(False)
    cursor_image = load_image("assets/sprites/UI/icons/cursor.png")
    # координаты курсора
    cursor_x, cursor_y = screen_center, screen.get_height() * 0.1
    # Фоновая музыка
    pygame.mixer.music.load("assets/audio/music/main_menu.ogg")
    # Воспроизведение музыки вечно
    pygame.mixer.music.play(-1)
    # Установка громкости
    pygame.mixer.music.set_volume(DEFAULT_MUSIC_VOLUME)
    # Цикл окна
    while is_open:
        # Переменная, становящайся True если было нажатие курсора
        # (предусмотрен как джойстик, так и обычная мышка)
        was_click = False
        # Обработка событий
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                is_open = False
            # Мышь
            if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                was_click = True
            # Клавиши
            if event.type == pygame.KEYDOWN:
                if event.key in (pygame.K_KP_ENTER, pygame.K_SPACE,
                                 pygame.K_RETURN):
                    # Музыка затухает (1 секунду), т.к. главный экран закроется
                    pygame.mixer.music.fadeout(1000)
                    return 1
                if event.key == CONTROLS["KEYBOARD_PAUSE"]:
                    # Музыка затухает (1 секунду), т.к. главный экран закроется
                    pygame.mixer.music.fadeout(1000)
                    return 0
            # Кастомное событие нажатия на кнопку
            if event.type == Button.PRESS_TYPE:
                # Текст нажатой кнопки (нужно для определения какая кнопка нажата
                # (гарантированно есть, т.к. устанавливается при инициализации)
                sender_text = event.dict["sender_text"]
                # Управление
                if sender_text == button_controls.text:
                    current_message_box = control_message_box
                    current_message_box.need_to_draw = True
                # Об игре
                elif sender_text == button_about.text:
                    current_message_box = about_message_box
                    current_message_box.need_to_draw = True
                # Играть
                elif sender_text == button_play.text:
                    # Музыка затухает (1 секунду), т.к. главный экран закроется
                    pygame.mixer.music.fadeout(1000)
                    return 1
                # Выход
                elif sender_text == button_exit.text:
                    # Музыка затухает (1 секунду), т.к. главный экран закроется
                    pygame.mixer.music.fadeout(1000)
                    return 0

        # Определение местоположения для курсора
        if joystick:
            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
            # Проверка на нажатие
            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.blit(background_image, (0, 0))
        # Рисуем весь ui
        ui_sprites.draw(screen)
        # Если есть диалог, то его тоже обновляем и рисуем
        if current_message_box:
            if current_message_box.need_to_draw:
                current_message_box.draw(screen)
            current_message_box.update(was_click)
        # Рисуем курсор поверх всего
        screen.blit(cursor_image, cursor_position)
        pygame.display.flip()
        # Обновляем состояние джойстика
        joystick = get_joystick() if check_any_joystick() else None
        clock.tick(FPS)
    return 0
コード例 #16
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()
コード例 #17
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)