Окно Pygame не отвечает, если некоторое время не обновляется - PullRequest
0 голосов
/ 25 июня 2019

Я пытаюсь научиться подкреплению с помощью "игры", которую я создал.

В моем основном цикле, когда я просто играю в свою игру, все работает нормально, если окно регулярно обновляется.

Тем не менее, после эпизода я хотел бы обучить своего агента, но если обучение занимает слишком много времени, в окне пигмейма отображается только «панель управления» (полоса с X для закрытия окна), и если я попробуйте закрыть, программа просто вылетает.

Есть ли простой способ справиться с этим? Другие решения говорят мне, что я должен регулярно вызывать некоторые функции Pygame, но если мне придется приостанавливать свое обучение, просто чтобы делать это время от времени, код станет немного грязным.

Ответы [ 2 ]

0 голосов
/ 25 июня 2019

Да, вам нужно регулярно звонить pygame.event.get; в противном случае очередь событий заполнится, и ваше окно перестанет отвечать.

Если вам нужно запустить долгосрочное задание в вашей игре, у вас есть следующие опции:

Ты сопрограмма

Если ваше долгосрочное задание можно разбить на более мелкие, быстрые шаги, вы можете использовать cooroutine, чтобы вернуть элемент управления вашему главному циклу, используя yield:

import pygame
import time

def long_running_task():
    i = 0
    while i < 300:
        time.sleep(0.01)
        print(i)
        i += 1
        yield i

def main():
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    rect = pygame.Rect((10, 250, 32, 32))
    direction = 1
    generator = None
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
            if e.type == pygame.KEYDOWN:
                if e.key == pygame.K_SPACE:
                    generator = long_running_task()

        screen.fill(pygame.Color('darkgrey'))
        rect.move_ip(5 if direction else -5, 0)
        pygame.draw.rect(screen, pygame.Color('dodgerblue'), rect)
        if not screen.get_rect().contains(rect):
            direction = not direction

        if generator:
            try: next(generator)
            except StopIteration: generator = None

        pygame.display.flip()
        clock.tick(60)

if __name__ == '__main__':
    main()

Это может работать, а может и не работать, но это хорошее решение, когда у вас есть алгоритм, который вычисляет результат, и вы хотите нарисовать экран между этапами этого алгоритма.

Запустите вашу задачу в другом потоке или процессе

Python позволяет довольно легко запускать функцию в другом процессе. Вот простой пример использования пакета multiprocessing.

import pygame
import time
import multiprocessing

def long_running_task():
    i = 0
    while i < 50:
        time.sleep(0.1)
        print(i)
        i += 1
    return i

def main():
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    rect = pygame.Rect((10, 250, 32, 32))
    direction = 1
    process = None
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                if process:
                    process.terminate()
                    process.join()
                return
            if e.type == pygame.KEYDOWN:
                if e.key == pygame.K_SPACE:
                    process = multiprocessing.Process(target=long_running_task) 
                    process.start()

        screen.fill(pygame.Color('darkgrey'))
        rect.move_ip(5 if direction else -5, 0)
        pygame.draw.rect(screen, pygame.Color('dodgerblue'), rect)
        if not screen.get_rect().contains(rect):
            direction = not direction

        pygame.display.flip()
        clock.tick(60)

if __name__ == '__main__':
    main()
0 голосов
/ 25 июня 2019

Обучающие циклы обучения усилению часто определяются в цикле while / for с обертками вокруг среды и агента.

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

Пример:

EPISODES = 100
env = gym.make("CartPole-v1")
for i in range(EPISODES):
    state = env.reset()
    steps = 0
    terminal = False
    while terminal is False:
        action = agent.sample(state)
        state, reward, terminal, info = env.step(action)

        if episode > 0:
            agent.train()

Полагаю, у вас нет спортивного зала, но это довольно легко сделать. Вы также можете создать свой собственный код, но общий поток приложения должен быть таким, как показано в примере кода.

...