PyGame отдельный поток для обработки ввода с клавиатуры - PullRequest
1 голос
/ 03 мая 2020

Я делаю игру со змеиным движением. Я считаю, что лучший способ добиться хорошего результата - создать отдельный поток для обработки ввода с клавиатуры пользователя. Вот моя функция, которую я хочу запустить в отдельном потоке:

    def _handle_keyboard_input(self):
        while self.is_running:
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:
                        self._set_velocity(-1, 0)
                    elif event.key == pygame.K_RIGHT:
                        self._set_velocity(1, 0)
                    elif event.key == pygame.K_UP:
                        self._set_velocity(0, -1)
                    elif event.key == pygame.K_DOWN:
                        self._set_velocity(0, 1)

    def _set_velocity(self, x, y):
        self._velocity_x = x
        self._velocity_y = y

Хотя я волнуюсь, будет ли постоянный цикл через это время загружать ЦП слишком сильно. Я думал о добавлении pygame.time.delay() задержек, но потом я не уверен, удастся ли мне «ударить» подходящий момент для события KEYDOWN (график c, который я нашел на этом сайте ниже).

Time interval for keyboard events

Я не хочу использовать pygame.key.get_pressed(), потому что я не хочу расставлять приоритеты для каких-либо клавиш (например, если клавиши со стрелками влево и вверх были нажаты одновременно, я придется выбрать один из них).

Каков наилучший подход к этому?

1 Ответ

1 голос
/ 03 мая 2020

Примечание pygame.event.get() удаляет события из очереди. Если у вас есть несколько циклов событий (даже в разных потоках), то вы пропустите события. Нет необходимости обрабатывать события чаще, чем дисплей обновляется, потому что изменения состояния становятся только «видимыми» после обновления дисплея. Поскольку события хранятся в очереди, нет необходимости получать события в «нужный» момент, pygame.event.get() получает и удаляет все ожидающие события из очереди.

Если вы хотите переместить Змея каждые 500 миллисекунд, тогда я рекомендую использовать pygame.time.Clock. Метод tick возвращает количество миллисекунд, прошедших с момента предыдущего вызова.
Суммируйте миллисекунды и перемещайте змею, когда сумма превышает 500:

clock = pygame.time.Clock()
count_ms = 0

FPS = 100
run = True
while run:
    passed_ms = clock.tick(FPS)

    # event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        # [...]

    count_ms += passed_ms
    if count_ms >= 500:
        count_ms = count_ms % 500

        # move and draw snake
        # [...]

        pygame.display.flip()
...