2012-06-19 5 views
6

Sto facendo un piccolo gioco e voglio creare un'altra finestra separatamente dalla mia principale.Visualizzazioni multiple in Pygame

Ho il gioco principale in una finestra principale, e voglio aprire una nuova finestra e fare una piccola animazione quando l'utente fa qualcosa.

Nel mio codice di esempio qui sotto, quando l'utente preme "a", desidero che apra una nuova finestra e faccia clic qui.

Qui ho istituito le due finestre: (so che questo non funziona, il suo quello che sto chiedendo come fare)

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

e quindi il programma:

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 

Finora ciò che fa è disegnare la schermata principale, quindi quando viene premuto A, smette di disegnare le animazioni della schermata principale, ma disegna ancora le altre animazioni sulla schermata principale e disegna nell'angolo in alto a sinistra.

Sono abbastanza sicuro che lo fa perché io pongo BATTLE_SCENE per essere più piccola della schermata principale, quindi quando copiarlo sul video per BATTLE_SCENE si Blits all'area ho creato (240x160) nell'angolo superiore della schermata principale.

Tuttavia voglio che BATTLE_SCENE diventi una finestra separata, in modo che quando premo 'a' verrà visualizzato, farà il suo effetto, quindi chiuderà o almeno tornerà dietro la schermata principale.

Come fare questo? È possibile?

+0

Non dovresti farlo comunque –

+0

Significa che c'è un modo per farlo? un po 'più di spiegazione sarebbe bello :) – hammythepig

+0

Crea un'area nella finestra esistente per le animazioni. –

risposta

8

Avete davvero bisogno di più finestre? Voglio dire, hai davvero bisogno di loro?

Se sì, allora probabilmente dovresti usare lo pyglet/cocos2d.

Per avere più finestre in pygame, sono necessari più processi (uno per ogni finestra). Mentre questo è fattibile, non ne vale la pena. Avrai bisogno dello IPC per scambiare dati tra le finestre, e immagino che il tuo codice diventerà soggetto a errori e brutto.

Vai con pyglet quando hai bisogno di più di una finestra.

La soluzione migliore è probabilmente quella di dividere il gioco in scene. Crea più scene in modo che ognuna rappresenti uno stadio del gioco, qualcosa come MenuScene, MainScene, BattleScene, GameOverScene, OptionScene ecc.

Quindi ciascuna di queste scene gestirà l'input/il disegno di quella stessa parte del gioco.

  • MenuScene gestisce disegno e di ingresso, ecc del menu del gioco
  • MainScene maniglie di disegno e di ingresso, ecc del gioco in esecuzione
  • BattleScene maniglie di disegno e di ingresso, ecc di tutto quello che fate in run_ani

Nel mainloop, basta passare il controllo sulla scena corrente implementando i metodi draw(), handle_event() e update().

Alcuni codici di esempio per ottenere l'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() 

Questo è un modo semplice per separare in modo pulito la logica del gioco e consentire cambio di contesto.

+0

Oh capisco, uso alcune classi. Non mi sono mai piaciute le lezioni perché sembravano così confuse, ma capisco cosa hai scritto lì. Penso che cercherò anche di approfondire le lezioni e apprendere più cose. Per ora ti sto rispondendo, questo sembra un modo semplice ed efficace per fare quello che voglio, grazie mille! :) – hammythepig

+0

è un'idea intelligente, condividendo la tua conoscenza di queste cose. Mi piace imparare tutte queste cose, è interessante e divertente allo stesso tempo. – hammythepig

1

====================================== Modifica ======= ===================

In realtà non funzionerà. Apperamente pygame supporta solo uno schermo, e quando si inizializza un altro, si chiude il primo. Rimarrai con due varibles, che in effetti sono la stessa superficie. Puoi fare in modo che il gioco aumenti le dimensioni della finestra e giochi la scena di battaglia al suo fianco, per fare ciò puoi chiamare nuovamente pygame.display.set_mode() con valori diversi. La varible che fa riferimento allo schermo di visualizzazione sarà comunque utilizzabile, poiché cambia il suo riferimento a quello nuovo. Dopo che la scena è finita puoi ridurre la finestra allo stesso modo.

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

In pratica, si esegue un ciclo e ogni iterazione di esso è il rendering e la visualizzazione di una nuova cornice. Quando si chiama una funzione all'interno di un ciclo, non continua a funzionare finché non si completa la funzione.

Un modo per risolvere questo problema è continuare a chiamare la funzione che aggiorna la scena di battaglia nel ciclo principale. Un altro modo è usare il threading. Il threading esegue fondamentalmente più script ("Thread") nello stesso tempo.

Fortunatamente Python lo ha già implementato con il modulo di threading. È troppo lungo per me spiegare il modulo qui, ma lo si può imparare here. Potrebbe essere un po 'complesso se non hai usato thread prima, ma dopo un po' di tempo sarà più facile. E se vuoi saperne di più sul threading puoi andare su here.

In questo caso, è possibile avere due thread, uno per ogni loop/finestra e eseguirli nello stesso momento.

Spero di averti aiutato!