Как с помощью библиотеки pygame сделать так, чтобы скорость игры не зависела от частоты обновления кадров?

Рейтинг: 1Ответов: 0Опубликовано: 02.06.2023

Я пишу свою первую игру с помощью библиотеки pygame, ниже представлен её код

import os
import sys
import pygame

# Инициализация Pygame
pygame.init()

# Определение размеров экрана пользователя
screen_info = pygame.display.Info()
window_width = screen_info.current_w
window_height = screen_info.current_h

# Создание окна с полноэкранным режимом и адаптацией под размеры экрана
window = pygame.display.set_mode((window_width, window_height), pygame.FULLSCREEN)
pygame.display.set_caption("game")

# Загрузка изображений
obstacle_image = pygame.image.load("obstacle.png")
background1_image = pygame.image.load("map2.png")
background1_image = pygame.transform.scale(background1_image, (window_width, window_height))
background2_image = background1_image

# Загрузка изображений для анимации бега
run_images = []
for i in range(9):
    image_path = os.path.join("man3", f"man{i}.png")
    image = pygame.image.load(image_path)
    run_images.append(image)

# Текущий индекс кадра анимации
current_frame = 0

# Скорость смены кадров анимации бега
animation_speed = 3

# Создание маски таракана
obstacle_mask = pygame.mask.from_surface(obstacle_image)

# Создание массива с масками каждого кадра анимации бега
player_masks = []
for player_image in run_images:
    mask = pygame.mask.from_surface(player_image)
    player_masks.append(mask)

# Получение размеров изображений
obstacle_width = obstacle_image.get_width()
obstacle_height = obstacle_image.get_height()
background1_width = background1_image.get_width()
background1_height = background1_image.get_height()

# Счёт очков
counter = 0
score1 = 0
score2 = 1

# Путь к файлу с рекордом
record_file_path = "record.txt"

# Загрузка текущего рекорда
if os.path.exists(record_file_path):
    with open(record_file_path, "r") as file:
        record = int(file.read())
else:
    record = 0

# Определение начальных координат игрока
player_x = window_width * 0.1
player_y = window_height * 0.45

# Определение начальных координат таракана
obstacle_x = window_width
obstacle_y = window_height * 0.67

# Определение начальных координат фона
background1_x = 0
background1_y = 0
background2_x = background1_width
background2_y = 0

# Определение начальных координат номера двери
number1_x = background1_width * 0.888
number1_y = background1_height * 0.435
number2_x = background1_width * 0.888 + background1_width
number2_y = background1_height * 0.435


# Определение скорости таракана и фона
obstacle_speed = 9
background_speed = 7

# Определение состояния прыжка игрока
is_jumping = False
jump_count = 30

clock = pygame.time.Clock()

# Скорость игры
fps = 60
time = 1000 // fps

# Изначальное состояние игры
game_state = "menu"

# Функция запускающая главное меню
def main_menu():
    while True:
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    return
                elif event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()
            elif event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        window.fill((0, 0, 0))  # Заливка окна черным цветом

        # Отображение текста и элементов главного меню
        font = pygame.font.Font(None, 36)
        text = font.render("Нажмите Enter чтобы начать", True, (255, 255, 255))
        text_rect = text.get_rect(center=(window_width // 2, window_height // 2))
        window.blit(text, text_rect)
        pygame.display.flip()
        clock.tick(fps)

# Основной игровой цикл
running = True
while running:
    if game_state == "menu":
        main_menu()
        game_state = "playing"  # После выхода из главного меню начинается игра
    elif game_state == "playing":
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
                pygame.quit()  # Завершение Pygame перед выходом
                sys.exit()  # Завершение программы

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    if not is_jumping:
                        is_jumping = True

        # Формула высоты и скорости прыжка
        if is_jumping:
            current_frame = 2
            if jump_count >= -30:
                player_y -= (jump_count * abs(jump_count)) * 0.02
                jump_count -= 1
            else:
                jump_count = 30
                is_jumping = False

        # Перемещение таракана
        if counter > 0:
            obstacle_x -= obstacle_speed
            if obstacle_x < -obstacle_width:
                obstacle_x = window_width

        # Перемещение первого кадра фона и номера двери
        background1_x -= background_speed
        number1_x -= background_speed
        if background1_x < -background1_width:
            background1_x = background1_width - background_speed
            number1_x = ((background1_width * 0.888) + background1_width) - background_speed
            counter += 1
            score1 += 2

        # Перемещение второго кадра фона и номера двери
        background2_x -= background_speed
        number2_x -= background_speed
        if background2_x < -background1_width:
            background2_x = background1_width - background_speed
            number2_x = ((background1_width * 0.888) + background1_width) - background_speed
            counter += 1
            score2 += 2

        # Проверка на столкновение таракана с игроком
        if player_masks[current_frame // animation_speed].overlap(obstacle_mask, (int(obstacle_x - player_x), int(obstacle_y - player_y))):
            game_state = "game_over"  # Если столкновение произошло, переход в режим "game_over"

        # Обновление рекорда
        if counter > record:
            record = counter

        # Отрисовка фона
        window.blit(background1_image, (background1_x, background1_y))
        window.blit(background2_image, (background2_x, background2_y))

        # Отрисовка счёта
        font = pygame.font.Font(None, 30)
        text = font.render("Счёт: "+str(counter), True, (255, 255, 255))
        text_rect = text.get_rect(center=(window_width * 0.05, window_height*0.15))
        window.blit(text, text_rect)

        # Отрисовка рекорда
        text_record = font.render("Рекорд: " + str(record), True, (255, 255, 255))
        text_record_rect = text.get_rect(center=(window_width * 0.05, window_height*0.1))
        window.blit(text_record, text_record_rect)

        # Отрисовка чётного номера двери
        font_number = pygame.font.Font(None, 20)
        number1 = font_number.render(str(score1), True, (242, 224, 20))
        number1_rect = number1.get_rect(center=(number1_x, number1_y))
        window.blit(number1, number1_rect)

        # Отрисовка нечётного номера двери
        number2 = font_number.render(str(score2), True, (242, 224, 20))
        number2_rect = number2.get_rect(center=(number2_x, number2_y))
        window.blit(number2, number2_rect)

        # Отрисовка анимации бега игрока
        window.blit(run_images[current_frame // animation_speed], (player_x, player_y))
        current_frame += 1
        if (current_frame // animation_speed >= len(run_images)) and (is_jumping == False):
            current_frame = 0

        # Отрисовка таракана
        if counter > 0:
            window.blit(obstacle_image, (obstacle_x, obstacle_y))

        # Обновление окна
        pygame.display.update()
        clock.tick(fps)

    elif game_state == "game_over":
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    game_state = "menu"  # При нажатии "Esc" возвращаемся в главное
            if event.type == pygame.QUIT:
                running = False
                break

        window.fill((0, 0, 0))  # Заливка окна черным цветом

        # Отображение текста меню Game Over
        font = pygame.font.Font(None, 36)
        text = font.render("Игра окончена", True, (255, 255, 255))
        text_rect = text.get_rect(center=(window_width // 2, window_height // 2))
        window.blit(text, text_rect)
        restart_text = font.render("Нажмите Esc чтобы вернуться в главное меню", True, (255, 255, 255))
        restart_rect = restart_text.get_rect(center=(window_width // 2, window_height // 2 + 50))
        window.blit(restart_text, restart_rect)

        # Возвращение значений к начальным
        counter = 0
        fps = 60
        player_x = window_width * 0.1
        player_y = window_height * 0.45
        obstacle_x = window_width
        obstacle_y = window_height * 0.67
        background1_x = 0
        background1_y = window_height - background1_height
        background2_x = background1_width
        background2_y = window_height - background1_height
        background3_x = background1_width * 2
        background3_y = window_height - background1_height
        number1_x = background1_width * 0.888
        number1_y = background1_height * 0.435
        number2_x = background1_width * 0.888 + background1_width
        number2_y = background1_height * 0.435
        obstacle_speed = 9
        background_speed = 7
        score1 = 0
        score2 = 1
        current_frame = 0

        is_jumping = False
        jump_count = 30

        pygame.display.flip()
        clock.tick(fps)
        frame_time = clock.get_time()
        if frame_time < time:
            pygame.time.delay(time - frame_time)

        # Сохранение рекорда в файл
        with open(record_file_path, "w") as file:
            file.write(str(record))

# Закрытие окна Pygame
pygame.quit()

Скорость игры зависит от значения переменной fps. Как я понимаю из за этого скорость зависит ещё и от производительности компьютера, потому что когда я начинал писать игру и она была ещё совсем примитивной, скорость была больше. Теперь когда я ставлю любое значение fps больше 60, скорость не меняется, а если ставлю меньше, она замедляется соответственно значению этой переменной. Но если я ставлю маленькую скорость, у меня просто медленно сменяются кадры картинка перестаёт быть плавной. Как сделать так, чтобы скорость игры не зависела от частоты обновления кадров?

Ответы

Ответов пока нет.