Сброс и перезапуск программы pygame не работает

#pygame #main #restart

Вопрос:

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

 import board as b

class Gui():
    def __init__(self):
        pygame.init()

        self.gamestate = b.GameState()

    def run(self):
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_r:
                        running = False
                        pygame.quit()
                        Gui().run

if __name__ == '__main__':
    Gui().run()
 

Что происходит, когда пользователь пытается перезапустить, так это то, что графический интерфейс закрывается, а цикл while завершается должным образом. Затем откроется новое окно, но оно не очистило состояние игры, поэтому мое состояние игры из предыдущего запуска все еще там. Я думал, что эта строка self.gamestate = b.GameState() создаст для меня новое игровое состояние, но, похоже, это не так. Вот краткий фрагмент из файла совета:

 class GameState:

    def __init__(self):
        self.board = s.start_position
 

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

Ответ №1:

Вы слишком усложнили систему. На самом деле вы рекурсивно создаете экземпляр нового Gui объекта и нового цикла приложения в существующий Gui объект и цикл приложения. Если GameState реализовано правильно, должно быть достаточно создать новый GameState объект и продолжить существующий цикл приложения вместо рекурсивного создания нового Gui экземпляра:

 import board as b

class Gui():
    def __init__(self):
        pygame.init()

        self.gamestate = b.GameState()

    def run(self):

        running = True
        while running:

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                    pygame.quit()

                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_r:
                        self.gamestate = b.GameState()

            # [...]

if __name__ == '__main__':
    Gui().run()
 

Инструкция self.board = s.start_position не создает новый объект платы. self.board и s.start_position ссылаются на один и тот же объект. Если вы измените один из объектов, другой объект, по-видимому, изменится таким же образом, поскольку существует только один объект.
Либо вам нужно сделать глубокую копию объекта доски при запуске игры, либо вам нужно сбросить объект при перезапуске игры.

Решением может быть использование модуля Python copy . deepcopy можно создать глубокую копию объекта:

 import copy
 
 self.board = copy.deepcopy(s.start_position)`
 

Обратите внимание, что не все объекты могут быть глубоко скопированы. Например, a pygame.Surface не может быть глубоко скопировано.

Комментарии:

1. К сожалению, похоже, что это не так. Я даже попытался поместить self.gamestate = b.GameState() и self.gamestate.board = s.start_board под нажатие клавиши, но плата все еще не затронута. Я также ввожу некоторые параметры в графический интерфейс, которые необходимо будет сбросить.

2. @eligolf В любом случае, ваш рекурсивный подход может вызвать побочные эффекты. Если мой подход не сработает, если вы что-то напутали в своем приложении.

3. Я посмотрю на это еще раз, но мои текущие 3 дня отладки никуда меня не привели 🙁 Все сбрасывается (журнал перемещений, поворот игрока и т. Д.). Только плата не обновляется должным образом, даже если я прямо говорю об этом.

4. Похоже, что объявление self.board = s.start_board изменяется с моим исходным s.start_board. Поэтому, когда я сбрасываю его, он действительно работает, но исходные значения изменились. У вас есть какие-нибудь идеи, как это исправить? Ваше решение хорошее, и я принимаю его как ответ, это какой-то другой вопрос.

5. @eligolf Я расширил ответ.