Несколько дисплеев в Pygame

я делаю небольшую игру, и я хочу сделать еще одно окно отдельно от моего основного.

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

в моем примере кода ниже, когда пользователь нажимает "a", я хочу, чтобы он открыл новое окно и blit туда.

здесь я установил два окна: (я знаю, что это не работает, его то, что я спрашиваю, как do)

SCREEN_X = 400
SCREEN_Y = 400
BSCREEN_X = 240
BSCREEN_Y = 160

BATTLE_SCENE = pygame.display.set_mode((BSCREEN_X, BSCREEN_Y))
SCREEN = pygame.display.set_mode((SCREEN_X, SCREEN_Y))

и затем программа:

def run_ani ():
    #Do animation, blitting to BATTLE_SCENE
    return

def main_game():
    ending=False
    while ending==False:
        clock.tick(30)
        for event in pygame.event.get():
            if event.type == pygame.QUIT: ending=True
            if event.type == KEYDOWN: # key down or up?
                if event.key == K_ESCAPE:
                    ending=True # Time to leave
                    print("Stopped Early by user")
                elif event.key == K_a:
                    run_ani()
        #Normal screen motion, blitting to SCREEN
        if ending: pygame.quit()
    return

пока что это делает рисует главный экран, а затем, когда нажата кнопка A, она перестает рисовать анимацию главного экрана, но все равно рисует другие анимации на главном экране и рисует в левом верхнем углу.

Я уверен, что он делает это потому, что я ставлю BATTLE_SCENE быть меньше, чем главный экран, таким образом, при blitting до BATTLE_SCENE Он blits в область, которую я создал (240x160) в верхнем углу основной экран.

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

как это сделать? Это вообще возможно?

2 ответов


вам действительно нужно несколько окон? Я имею в виду, они тебе действительно нужны?

если да, то вы должны, вероятно, использовать pyglet/Cocos2d отличается.

чтобы иметь несколько окон в pygame, вам нужно несколько процессов (по одному для каждого окна). Хотя это выполнимо, это не стоит усилий. Вам понадобится IPC для обмена данными между окнами, и я думаю, что ваш код станет подверженным ошибкам и уродливым.

пойти с pyglet, когда вам нужно больше одного окна.

лучшее решение, вероятно, разделить вашу игру на сцены. Создать несколько сцен, так что каждый представляет один этап игры, что-то вроде MenuScene, MainScene, BattleScene, GameOverScene, OptionScene и т. д.

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

  • MenuScene регулирует чертеж и входной сигнал etc. меню игры
  • MainScene ручки рисуя и input etc. бегущей игры
  • BattleScene регулирует чертеж и входной сигнал etc. что бы вы ни делали в run_ani

в вашем mainloop просто передайте управление текущей сцене, реализовав методы draw(), handle_event() и update().

некоторый пример кода, чтобы получить идею:

scenes = {'Main': MainScene(),
          'Battle': BattleScene()} #etc

scene = scenes['Main']

class MainScene():
  ...
  def handle_event(self, event):
    if event.type == KEYUP:
      if event.key == K_a:
        scene = scenes['Battle']
  ...

class BattleScene():
  ...
  def draw(self):
    # draw your animation

  def update(self):
    # if animation is over:
    scene = scenes['Main']

...

def main_game():
  ending=False
  While Not ending:
      clock.tick(30)
      for event in pygame.event.get():
        scene.handle_event(event)
        scene.update()
        scene.draw()

Это простой способ четко отделить логику игры и разрешить переключение контекста.


======================================изменить=========================================

на самом деле это не сработает. Apperantly pygame поддерживает только один экран дисплея, и когда вы инициализируете другой, он закроет первый. Вы останетесь с двумя varibles, которые на самом деле являются одной и той же поверхности. Вы можете вместо игры увеличить размер окна и играть в битву на его стороне, для этого вы можете вызвать pygame.дисплей.set_mode() снова с другой ценности. В настройка который ссылается экран по-прежнему можно использовать, как изменить свою ссылку на новый. После того, как сцена закончится, вы можете уменьшить окно обратно таким же образом.

==================================================================================

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

один из способов решить эту проблему - просто продолжать вызывать функцию, которая обновляет сцену битвы в основном цикле. Другой способ - использовать threading. Threading в основном запускает несколько сценариев ("потоков") одновременно.

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

конкретно здесь вы можете иметь два потока, по одному для каждого цикла / окна, и запускать их одновременно.

надеюсь, я помог вам!