#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 Я расширил ответ.