Risolto Riavvio VIdeogioco in Python

KHAN21

Utente Bronze
9 Gennaio 2021
36
16
3
29
Buongiorno, sto facendo un videogioco simile a flappy bird per un compito di informatica insieme a dei miei compagni(che non stanno facendo un emerita mazza) e ho creato un pop up che esce fuori quando muori con yes e no, e quando premi su no il videogioco si chiude, ma, quando premi su yes per continuare a giocare il programma non si riavvia e il pop up non scompare. Ringrazio anticipamente per le risposte.
Python:
#importo tutte le librerie che mi servono
import pygame
import time
from random import randint,randrange
from tkinter import *
from tkinter import messagebox


black= (0,0,0)
white= (255,255,255)

sunset = (253,72,47)
greenyellow=(184,255,0)
brightblue=(47,228,253)
orange=(255,236,0)
yellow=(255,236,0)
purple=(252,67,255)

colorChoices = [greenyellow,brightblue,orange,yellow,purple]
#assegno dei colori come tuple in modo da poterli ricavare, e creo una lista con tutti i colori


pygame.init()#inizializzo python

surfaceWidth = 800#do la lunghezza della finestra
surfaceHeight = 500#do l'altezza della finestra

imageHeight = 100#mi salvo l'altezza dell'immagine
imageWidth= 100#mi salvo lo spessore dell'immagine

surface = pygame.display.set_mode((surfaceWidth,surfaceHeight))#inizializzo la finestra usando le variabili surfaceWidth e surfaceHeight
pygame.display.set_caption('Jupiter Escape by me')#do il nome alla finestra
clock=pygame.time.Clock()#creo un "orologio" che calcola il tempo

img=pygame.image.load('Helicopter.jpg')#inizializzo la navicella

def score(count):#creo la funzione che stamperà i punti
  font = pygame.font.Font('freesansbold.ttf',20)#inizializzo font e grandezza della scritta
  text = font.render("Score: "+str(count), True, white)#creo una "lavagna" su cui stampo score + il punteggio, gli do il true per creare la scritta con angoli smussati e gli do il colore bianco
  surface.blit(text, [0,0])#incollo la lavagna scritta prima in alto a destra


def blocks(x_block,y_block,block_width,block_height,gap,colorChoice):
 
  pygame.draw.rect(surface,colorChoice,[x_block,y_block,block_width,block_height])
  pygame.draw.rect(surface,colorChoice,[x_block,y_block+block_height+gap,block_width,surfaceHeight])

def replay_or_quit():
  for event in pygame.event.get([pygame.KEYDOWN,pygame.KEYUP, pygame.QUIT]):
    if event.type==pygame.QUIT:
      pygame.quit()
      quit()
    elif event.type == pygame.KEYDOWN:
      continue
    return event.key
  return None


def gameOver():
  Tk().wm_withdraw() #nascondo la finestra del gioco
  if messagebox.askyesno('Hai perso!','Vuoi riprovare?') == False:
    pygame.quit()
    quit()
 
def helicopter(x,y,image):
  surface.blit(img, (x,y))

def main():
  x= 150
  y= 200
  y_move = 0

  x_block = surfaceWidth
  y_block = 0

  block_width = 75
  block_height = randint(0, (surfaceHeight/2))
  gap = imageHeight * 3
  block_move = 4

  current_score=0
  blockColor= colorChoices[randrange(0,len(colorChoices))]

  game_over = False
  while not game_over:
    for event in pygame.event.get():
      if event.type == pygame.QUIT:
        game_over=True


      if event.type== pygame.KEYDOWN:
        if event.key == pygame.K_UP:
          y_move = -5

      if event.type == pygame.KEYUP:
        if event.key == pygame.K_UP:
          y_move = 5
    y += y_move
   
    surface.fill(black)
    helicopter(x,y,img)

   

    blocks(x_block, y_block, block_width, block_height, gap,blockColor)
    score(current_score)

    x_block -= block_move

    if y > surfaceHeight or y < 0:
      gameOver()

    if x_block < (-1*block_width):
      x_block = surfaceWidth
      block_height = randint(0, surfaceHeight/2)
      blockColor= colorChoices[randrange(0,len(colorChoices))]
    if x+imageWidth > x_block:
      if x<x_block+block_width:
     
        if y<block_height:
           
            if x - imageWidth < block_width + x_block:
         
              gameOver()
    if x + imageWidth > x_block:
 

      if y + imageHeight > block_height + gap:
   

        if x < block_width + x_block:
          gameOver()
    if x < x_block and x>x_block - block_move:
      current_score +=1


    pydef gameOver():
  Tk().wm_withdraw() #nascondo la finestra del gioco
  if messagebox.askyesno('Hai perso!','Vuoi riprovare?') == False:
    pygame.quit()
    quit()
  elif messagebox.askyesno('Hai perso!','Vuoi riprovare?') == True:
    game_over = False
    main()game.display.update()
    clock.tick(60)

main()
pygame.quit()
quit()
 
Queste due linee:
Python:
pydef gameOver():
# ...
main()game.display.update()
che hai scritto verso fine codice, non hanno usa sintassi valida. Non ho modo di provare il tuo codice correttamente (mi manca l'immagine e il font), ma il problema del popup che non scompare è dovuto al fatto che stai creando due messagebox: una nell'if e una nell'elseif. Probabilmente volevi scrivere una cosa di questo tipo:
Python:
def gameOver():
  Tk().wm_withdraw()
  if messagebox.askyesno('Hai perso!','Vuoi riprovare?') == False:
    quit()
  else:
    game_over = False
    main()
Il tuo codice sia da sistemare anche in altri punti, ma non vorrei rimetterci mano in modo troppo pesante. Penso che pygame.display.update() sia da chiamare ad ogni giro del while, cosa che tu non stai facendo. In generale, fare una chiamata ricorsiva a main per far ripartire il gioco non è una buona idea... ma vabbé. Vedi se riesci a ripulirlo un po' e se nessun altro risponde domani vedo di ritoccartelo un attimino.
 
ok grazie @St3ve , ho migliorato cosi ma mi da ancora il problema col pop-up:
Python:
#importo tutte le librerie che mi servono
import pygame
import time
from random import randint,randrange
from tkinter import *
from tkinter import messagebox


black= (0,0,0)
white= (255,255,255)

sunset = (253,72,47)
greenyellow=(184,255,0)
brightblue=(47,228,253)
orange=(255,236,0)
yellow=(255,236,0)
purple=(252,67,255)

colorChoices = [greenyellow,brightblue,orange,yellow,purple]
#assegno dei colori come tuple in modo da poterli ricavare, e creo una lista con tutti i colori


pygame.init()#inizializzo python

surfaceWidth = 800#do la lunghezza della finestra
surfaceHeight = 500#do l'altezza della finestra

imageHeight = 100#mi salvo l'altezza dell'immagine
imageWidth= 100#mi salvo lo spessore dell'immagine

surface = pygame.display.set_mode((surfaceWidth,surfaceHeight))#inizializzo la finestra usando le variabili surfaceWidth e surfaceHeight
pygame.display.set_caption('Jupiter Escape by Kiwhen, Grigolon, Karaj, Dobrovolski and fogarolo')#do il nome alla finestra
clock=pygame.time.Clock()#creo un "orologio" che calcola il tempo

img=pygame.image.load('ufo.jpg')#inizializzo la navicella

def score(count):#creo la funzione che stamperà i punti
  font = pygame.font.Font('freesansbold.ttf',20)#inizializzo font e grandezza della scritta
  text = font.render("Score: "+str(count), True, white)#creo una "lavagna" su cui stampo score + il punteggio, gli do il true per creare la scritta con angoli smussati e gli do il colore bianco
  surface.blit(text, [0,0])#incollo la lavagna scritta prima in alto a destra


def blocks(x_block,y_block,block_width,block_height,gap,colorChoice):#funzione che disegna gli ostacoli
 
  pygame.draw.rect(surface,colorChoice,[x_block,y_block,block_width,block_height])#istruzione che crea gli ostacoli prendendo la finestra, i colori, le coordinate x e y, l'altezza e lo spessore degli ostacoli
  pygame.draw.rect(surface,colorChoice,[x_block,y_block+block_height+gap,block_width,surfaceHeight])#istuzione che crea gli ostacoli prendendo la finestra, i colori, le coordinate x, y + l'altezza e il buco, l'altezza e lo spessore degli ostacoli


def gameOver():
  Tk().wm_withdraw() #nascondo la finestra del gioco
  a = messagebox.askretrycancel('Hai perso!','Vuoi riprovare?')#inizializzo il pop up con i tasti yes e no e controllo se viene premuto no
  if a == False:
    pygame.quit()
    quit()
  else:
    game_over = False
    main()



 
def ufo(x,y,image):#funzione che piazza l'ufo
  surface.blit(img, (x,y))#inizializzo l'ufo con questa funzione che ha come parametri l'immagine e le coordinate


def main():
  x= 150
  y= 200
  y_move = 0

  x_block = surfaceWidth
  y_block = 0

  block_width = 75
  block_height = randint(0, (surfaceHeight/2))
  gap = imageHeight * 3
  block_move = 4

  current_score=0
  blockColor= colorChoices[randrange(0,len(colorChoices))]

  game_over = False
  gameClose = False
  while not game_over:
    for event in pygame.event.get():
      if event.type == pygame.QUIT:
        game_over=True


      if event.type== pygame.KEYDOWN:
        if event.key == pygame.K_UP:
          y_move = -5

      if event.type == pygame.KEYUP:
        if event.key == pygame.K_UP:
          y_move = 5
    y += y_move
 
    surface.fill(black)
    ufo(x,y,img)

 
 
    blocks(x_block, y_block, block_width, block_height, gap,blockColor)
    score(current_score)

    x_block -= block_move

    if y > surfaceHeight or y < 0:
      gameOver()

    if x_block < (-1*block_width):
      x_block = surfaceWidth
      block_height = randint(0, surfaceHeight/2)
      blockColor= colorChoices[randrange(0,len(colorChoices))]
    if x+imageWidth > x_block:
      if x<x_block+block_width:
  
        if y<block_height:
        
            if x - imageWidth < block_width + x_block:
      
              gameOver()
    if x + imageWidth > x_block:
 

      if y + imageHeight > block_height + gap:
 

        if x < block_width + x_block:
          gameOver()
    if x < x_block and x>x_block - block_move:
      current_score +=1


    pygame.display.update()
    clock.tick(60)

main()
pygame.quit()
quit()
 
Python:
def gameOver():
  tk = Tk()
  tk.wm_withdraw()
  a = messagebox.askretrycancel('Hai perso!','Vuoi riprovare?')#inizializzo il pop up con i tasti yes e no e controllo se viene premuto no
  tk.update()
  if a == False:
    pygame.quit()
    quit()
  else:
    game_over = False
    main()
 
Python:
def gameOver():
  tk = Tk()
  tk.wm_withdraw()
  a = messagebox.askretrycancel('Hai perso!','Vuoi riprovare?')#inizializzo il pop up con i tasti yes e no e controllo se viene premuto no
  tk.update()
  if a == False:
    pygame.quit()
    quit()
  else:
    game_over = False
    main()
Ok @St3ve grazie ancora per il tuo aiuto, ma quando premo si il gioco riparte ma rimane un pop up vuoto. Sapresti come risolvere anche questo?
 
Python:
#importo tutte le librerie che mi servono
import pygame
import time
from random import randint,randrange
from tkinter import *
from tkinter import messagebox

black= (0,0,0)
white= (255,255,255)

sunset = (253,72,47)
greenyellow=(184,255,0)
brightblue=(47,228,253)
orange=(255,236,0)
yellow=(255,236,0)
purple=(252,67,255)

colorChoices = [greenyellow,brightblue,orange,yellow,purple]
#assegno dei colori come tuple in modo da poterli ricavare, e creo una lista con tutti i colori


pygame.init()#inizializzo python

surfaceWidth = 800#do la lunghezza della finestra
surfaceHeight = 500#do l'altezza della finestra

imageHeight = 100#mi salvo l'altezza dell'immagine
imageWidth= 100#mi salvo lo spessore dell'immagine

surface = pygame.display.set_mode((surfaceWidth,surfaceHeight))#inizializzo la finestra usando le variabili surfaceWidth e surfaceHeight
pygame.display.set_caption('Jupiter Escape by Kiwhen, Grigolon, Karaj, Dobrovolski and fogarolo')#do il nome alla finestra
clock=pygame.time.Clock()#creo un "orologio" che calcola il tempo
bg = pygame.image.load("background.jpg")#iniziallizzo il background
img=pygame.image.load('ufo.jpg')#inizializzo la navicella

def score(count):#creo la funzione che stamperà i punti
  font = pygame.font.Font('freesansbold.ttf',20)#inizializzo font e grandezza della scritta
  text = font.render("Score: "+str(count), True, white)#creo una "lavagna" su cui stampo score + il punteggio, gli do il true per creare la scritta con angoli smussati e gli do il colore bianco
  surface.blit(text, [0,0])#incollo la lavagna scritta prima in alto a destra


def blocks(x_block,y_block,block_width,block_height,gap,colorChoice):#funzione che disegna gli ostacoli
 
  pygame.draw.rect(surface,colorChoice,[x_block,y_block,block_width,block_height])#istruzione che crea gli ostacoli prendendo la finestra, i colori, le coordinate x e y, l'altezza e lo spessore degli ostacoli
  pygame.draw.rect(surface,colorChoice,[x_block,y_block+block_height+gap,block_width,surfaceHeight])#istuzione che crea gli ostacoli prendendo la finestra, i colori, le coordinate x, y + l'altezza e il buco, l'altezza e lo spessore degli ostacoli


def gameOver():
  tk = Tk()
  Tk().wm_withdraw() #nascondo la finestra del gioco
  a = messagebox.askretrycancel('Hai perso!','Hai perso, Riavvia per continuare a giocare!')#inizializzo il pop up
  tk.update()
  if a == False:
    pygame.quit()
    quit()
  else:
    game_over = False
    main()

def background(bg):
  surface.blit(bg, (0,0))

 
def ufo(x,y,image):#funzione che piazza l'ufo
  surface.blit(img, (x,y))#inizializzo l'ufo con questa funzione che ha come parametri l'immagine e le coordinate


def main():
  x= 150#assegno le coordinate del ufo
  y= 200
  y_move = 0#assegno la variabile del movimento

  x_block = surfaceWidth#assegno le variabili delle coordinate dei blocchi
  y_block = 0

  block_width = 75#assegno la lunghezza dei blocchi
  block_height = randint(0, (surfaceHeight/2))#assegno l'altezza randomica dei blocchi
  gap = imageHeight * 3#assegno il "buco" tra gli ostacoli
  block_move = 4

  current_score=0#inizializzo il punteggio
  blockColor= colorChoices[randrange(0,len(colorChoices))]#iniziallizzo la variabile dei colori del blocco

  game_over = False
  while not game_over:
    for event in pygame.event.get():
      if event.type == pygame.QUIT:
        game_over=True


      if event.type== pygame.KEYDOWN:
        if event.key == pygame.K_UP:
          y_move = -5

      if event.type == pygame.KEYUP:
        if event.key == pygame.K_UP:
          y_move = 5
    y += y_move
   
    background(bg)
    ufo(x,y,img)
   
   
 
    blocks(x_block, y_block, block_width, block_height, gap,blockColor)
    score(current_score)

    x_block -= block_move

    if y > surfaceHeight or y < 0:
      gameOver()

    if x_block < (-1*block_width):
      x_block = surfaceWidth
      block_height = randint(0, surfaceHeight/2)
      blockColor= colorChoices[randrange(0,len(colorChoices))]
    if x+imageWidth > x_block:
      if x<x_block+block_width:
     
        if y<block_height:
           
            if x - imageWidth < block_width + x_block:
         
              gameOver()
    if x + imageWidth > x_block:
 

      if y + imageHeight > block_height + gap:
   

        if x < block_width + x_block:
          gameOver()
    if x < x_block and x>x_block - block_move:
      current_score +=1


    pygame.display.update()
    clock.tick(60)


main()
pygame.quit()
quit()
ecco qui tutto @St3ve
 
Ultima modifica:
grazie mille di tutto @St3ve, ora funziona!
Messaggio unito automaticamente:

scusa per quest'ultima domanda @St3ve, ma se volessi creare un pop up anche per il menu del gioco ricopio quella parte mettendola nel main modificando i valori giusto?
 
scusa per quest'ultima domanda @St3ve, ma se volessi creare un pop up anche per il menu del gioco ricopio quella parte mettendola nel main modificando i valori giusto?
Non sono pratico di tkinter, dovrei leggere anche io sulla documentazione. Fai un tentativo e vedi come va, mal che vada avrai qualche altro problema e se posti il codice (tempo permettendo) posso vedere di sbrigarmela io.
 
A quanto pare ha funzionato! mi stavo chiedendo se ti potevo disturbare ancora, dato che, mi è venuto in mente di creare un tasto con qui far accelerare la navicella e ho provato così:
Python:
while not game_over:#creo il ciclo del gioco
    for event in pygame.event.get():#analizzo tutti gli eventi in input
      if event.type == pygame.QUIT:#controllo se è stato dato il comando quit
        game_over = True#se si do true a game over
        pygame.quit()
        quit()


      if event.type== pygame.KEYDOWN:
        if event.key == pygame.K_UP or event.key == ord('w'):
          y_move = -5

      if event.type == pygame.KEYUP:
        if event.key == pygame.K_UP or event.key == ord('w'):
          y_move = 5

      if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_TAB:
          x_move = 5

      if event.type == pygame.KEYUP:
        if event.key == pygame.K_TAB:
          x_move += 0   

    y += y_move
    x += x_move
il problema si pone quando lo premo, e la navicella accelera fino ad uscire dalla finestra.
Se mi potresti dare una mano tu @St3ve o qualcun altro vi sarei grato, ma tranquilli che per questo non ho una scadenza:)
 
L'illusione che la navicella si sposta tu ce l'hai con la visione del mondo che ti scorre davanti. Se vuoi farla andare più veloce non devi spostare la navicella, ma cambiare la velocità del mondo.
Python:
if event.type == pygame.KEYDOWN:
  if event.key == pygame.K_TAB: 
    block_move = 16             
                                
if event.type == pygame.KEYUP:  
  if event.key == pygame.K_TAB: 
    block_move = 4
Volendo puoi creare un effetto di accelerazione / decelerazione usando la classica formula $$\(v = at + u$$\).
 
Per far sparare la navicella fai più o meno la stessa cosa che stai facendo per i blocchi: disegni un rettangolino con pygame.draw.rect che parte dal centro della navicella e si muove verso destra (invece che verso sinistra). Il nemico dipende un po' da come vuoi farlo, ma in prima approssimazione puoi semplicemente prendere uno sprite, piazzarlo all'interno del gap e farlo avvicinare a te a velocità doppia o tripla rispetto ai blocchi.

P.S. per lo sviluppo di videogiochi viene comoda la programmazione object oriented, se non l'hai mai studiata ti consiglio di guardarla perché pulirebbe il tuo codice significativamente.