2012-06-19 106 views
6

Estoy haciendo un pequeño juego y quiero hacer otra ventana aparte de la principal.Múltiples pantallas en Pygame

Tengo el juego principal en una ventana principal, y quiero abrir una nueva ventana y hacer una pequeña animación cuando el usuario hace algo.

En mi código de ejemplo a continuación, cuando el usuario presiona "a" quiero que abra una nueva ventana y blit hasta allí.

Aquí puedo configurar las dos ventanas: (Sé que esto no funciona, es lo que estoy preguntando cómo hacerlo)

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)) 

y luego el programa:

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 

Hasta ahora lo que hace esto es dibujar la pantalla principal, luego cuando se presiona A, deja de dibujar las animaciones de la pantalla principal, pero aún dibuja las otras animaciones en la pantalla principal y dibuja en la esquina superior izquierda.

estoy bastante seguro de que hace esto porque yo soy la creación BATTLE_SCENE sea más pequeña que la pantalla principal, por lo tanto, cuando blitting a BATTLE_SCENE que Blits a la zona creé (240x160) en la esquina superior de la pantalla principal.

Sin embargo, quiero que BATTLE_SCENE sea una ventana separada, de modo que cuando presione 'a' aparezca, haga lo suyo, luego cierre o al menos vaya detrás de la pantalla principal.

¿Cómo hacer esto? ¿Es posible?

+0

No debe hacer esto de todos modos –

+0

¿Eso significa que hay una manera en que debería hacerlo? un poco más de explicación sería bueno :) – hammythepig

+0

Haz un área en la ventana existente para las animaciones. –

Respuesta

8

¿Realmente necesita varias ventanas? Quiero decir, ¿realmente los necesitas?

En caso afirmativo, probablemente debería usar pyglet/cocos2d en su lugar.

Para tener múltiples ventanas en pygame, necesita múltiples procesos (uno para cada ventana). Si bien esto es factible, no vale la pena el esfuerzo. Necesitarás IPC para intercambiar datos entre las ventanas, y supongo que tu código se volverá propenso a errores y feo.

Vaya con pyglet cuando necesite más de una ventana.

La mejor solución es, probablemente, dividir el juego en escenas. Cree varias escenas para que cada una represente una etapa del juego, como MenuScene, MainScene, BattleScene, GameOverScene, OptionScene, etc.

Luego, deje que cada una de esas escenas maneje la entrada/dibujo de esa parte del juego.

  • MenuScene se encarga de dibujo y de entrada, etc., de menú del juego
  • MainScene maneja el dibujo y la entrada etc. del juego terrestre
  • BattleScene maneja el dibujo y la entrada, etc., de cualquier cosa que hagas en run_ani

En su mainloop, simplemente pase el control a la escena actual implementando los métodos draw(), handle_event() y update().

un código de ejemplo para obtener la idea:

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() 

Esta es una manera fácil de separar limpiamente la lógica del juego y permitir el cambio de contexto.

+0

Oh veo, usa algunas clases. Nunca me gustaron las clases porque parecían muy confusas, pero entiendo lo que escribiste allí. Creo que incluso estudiaré más las clases y aprenderé más cosas. Por ahora estoy respondiendo, esta parece ser una forma simple y efectiva de hacer lo que quiero, ¡muchas gracias! :) – hammythepig

+0

eso es una idea inteligente, compartiendo su conocimiento de tales cosas. Me gusta aprender todo esto, es interesante y divertido al mismo tiempo. – hammythepig

1

================================ Edición ======= ============================

En realidad, no funcionará. Aparentemente, pygame solo admite una pantalla, y cuando inicializa otra, cerrará la primera. Te quedarás con dos varibles, que de hecho son de la misma superficie. En su lugar, puede hacer que el juego aumente el tamaño de la ventana y que se reproduzca la escena de batalla en el costado, para ello puede volver a llamar a pygame.display.set_mode() con diferentes valores. La variable que hace referencia a la pantalla de visualización seguirá siendo utilizable, ya que cambia su referencia a la nueva. Después de que termine la escena, puede disminuir la ventana de nuevo de la misma manera.

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

Lo que básicamente sucede es que ejecuta un ciclo, y cada iteración de este es renderizar y mostrar un nuevo marco. Cuando llama a una función dentro de un bucle, no continúa ejecutándose hasta que termine de ejecutar la función.

Una forma de resolver este problema es simplemente seguir llamando a la función que actualiza la escena de batalla en el ciclo principal. Otra forma es mediante el uso de subprocesos. Enhebrar es básicamente ejecutar múltiples scripts ("Threads") al mismo tiempo.

Afortunadamente, python ya lo implementó para nosotros con el módulo de subprocesamiento. Es demasiado tiempo para explicar el módulo aquí, pero puede aprenderlo here. Puede ser un poco complejo si no ha usado subprocesos antes, pero después de un tiempo será más fácil. Y si desea obtener más información acerca de cómo enhebrar puede ir al here.

Específicamente aquí, puede tener dos hilos, uno para cada bucle/ventana, y ejecutarlos al mismo tiempo.

Espero te ayudé!