def rainbow_effect_on_water(screen: pygame.surface.Surface, water_tile: pygame.surface.Surface) -> None: orig_screen = screen.copy() water_color = pygame.transform.average_color(water_tile, water_tile.get_rect()) # Cycle through the rainbow colors clock = pygame.time.Clock() for i in range(4): for rainbow_color in rainbow_colors: try: pygame.transform.threshold(screen, orig_screen, search_color=water_color, threshold=pygame.Color(50, 50, 50), set_color=rainbow_color, inverse_set=True) clock.tick(5) pygame.display.flip() except: print('Color not found: ', rainbow_color, flush=True) # Restore original screen screen.blit(orig_screen, (0, 0)) pygame.display.flip()
def update(self, screen: pygame.surface.Surface) -> bool: self.rect = screen.get_rect() self.update_humans_to_zombies() self.update_eaten_food() self.check_and_fix_edges() self.check_food() return not self.all_dead()
def __init__(self, pos: tuple, method, image: pygame.surface.Surface, text: pygame.surface.Surface, mixer, *groups, args: tuple = (), anchor: tuple = (0, 0)): image.blit(text, (image.get_rect().centerx - text.get_rect().centerx, image.get_rect().centery - text.get_rect().centery)) self.method = method self.args = args self.mixer = mixer super().__init__(pos, image, *groups, anchor=anchor)
def draw(self, surface: pygame.surface.Surface) -> None: # tell the map_layer (BufferedRenderer) to draw to the surface # the draw function requires a rect to draw to. self.map_layer.draw(surface, surface.get_rect()) # blit our text over the map self.draw_text(surface)
def replace_circle(self, image: pygame.surface.Surface): """[summary]. Args: image (pygame.surface.Surface): [description]. """ sprite = SimpleSprite(rect=image.get_rect(), image=image) sprite.rect.center = self.badgesprite.center self.badgesprite.add(sprite) self.add(sprite)
def drawForeground( self: "MapView", screen: pg.surface.Surface, position: Vector, # World position texture: pg.surface.Surface, ) -> None: w, h = texture.get_rect().size scaledHeight = int(h * self.zoomRatio) scaledTexture = pg.transform.scale(texture, (self.scaledTileSize, scaledHeight)) screenPos = self.worldToScreen(position) topLeft = screenPos + Vector(0, self.scaledTileSize - scaledHeight) screen.blit(scaledTexture, topLeft.toTuple())
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)
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)
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()
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)
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) # 시간 업데이트