44from pgzero .actor import Actor
55from types import SimpleNamespace
66
7+ # ===== CONFIGURAZIONE INIZIALE =====
78WIDTH = 800
89HEIGHT = 600
9- TITLE = "La Battaglia Finale"
10+ TITLE = "La Battaglia Finale: Harry vs Voldemort "
1011
12+ # Variabili globali per lo stato del gioco
1113punti_vita = {"Harry" : 100 , "Voldemort" : 100 }
14+ # SimpleNamespace permette di animare i valori come se fossero proprietà di un oggetto
1215visualizzazione = SimpleNamespace (Harry = 100 , Voldemort = 100 )
13-
14- harry_sprite = Actor ('harry' , (200 , 320 ))
15- voldy_sprite = Actor ('voldemort' , (600 , 150 ))
16-
16+ # Variabili di controllo del flusso
1717messaggio = "VOLDEMORT è apparso!"
1818descrizione = "Cosa farà HARRY?"
19- attesa_input = True
19+ attesa_input = True
2020gioco_attivo = True
2121
22+ # Creazione degli sprite
23+ harry_sprite = Actor ("harry" , (200 , 320 ))
24+ voldy_sprite = Actor ("voldemort" , (600 , 150 ))
25+
2226# --- Caricamento Dati ---
23- incantesimi_df = pl .read_csv (r"C:\Users\alema\Desktop\pythonbiella\LearningPythonWithGames\game11\spells.csv" )
27+ incantesimi_df = pl .read_csv (
28+ r"C:\Users\alema\Desktop\pythonbiella\LearningPythonWithGames\game11\spells.csv"
29+ )
30+
2431
2532def ottieni_opzioni (personaggio ):
33+ """Filtra il DataFrame per ottenere solo gli incantesimi di un personaggio specifico."""
2634 return incantesimi_df .filter (pl .col ("character" ) == personaggio )
2735
36+
37+ # Effetti Visivi
38+
39+
2840def flash_danno (sprite ):
29- """Fa lampeggiare lo sprite e lo scuote leggermente ."""
41+ """Crea un effetto visivo di scossa e lampeggio quando uno sprite subisce danni ."""
3042 x_originale = sprite .x
31- # Scossa rapida
32- animate (sprite , duration = 0.5 , x = x_originale + 10 , tween = ' bounce_end' )
33- # Lampeggio
43+ # Animazione di scossa
44+ animate (sprite , duration = 0.5 , x = x_originale + 10 , tween = " bounce_end" )
45+ # Ciclo per far sparire e riapparire lo sprite
3446 for i in range (3 ):
35- clock .schedule_unique (lambda : setattr (sprite , 'opacity' , 0 ), i * 0.2 )
36- clock .schedule_unique (lambda : setattr (sprite , 'opacity' , 255 ), i * 0.2 + 0.1 )
37- # Ripristina posizione
38- clock .schedule_unique (lambda : setattr (sprite , 'x' , x_originale ), 0.3 )
47+ clock .schedule_unique (lambda : setattr (sprite , "opacity" , 0 ), i * 0.5 )
48+ clock .schedule_unique (lambda : setattr (sprite , "opacity" , 255 ), i * 0.5 + 0.1 )
49+ # Ripristina la posizione originale dopo l'effetto
50+ clock .schedule_unique (lambda : setattr (sprite , "x" , x_originale ), 0.6 )
51+
52+
53+ # Logica di Gioco
54+
55+
56+ def reset_gioco ():
57+ """Ripristina lo stato iniziale per una nuova partita."""
58+ global \
59+ punti_vita , \
60+ visualizzazione , \
61+ messaggio , \
62+ descrizione , \
63+ attesa_input , \
64+ gioco_attivo
65+ punti_vita = {"Harry" : 100 , "Voldemort" : 100 }
66+ visualizzazione .Harry = 100
67+ visualizzazione .Voldemort = 100
68+ messaggio = "Nuovo Duello!"
69+ descrizione = "Cosa farà HARRY?"
70+ attesa_input = True
71+ gioco_attivo = True
72+ # Ripristina opacità
73+ harry_sprite .opacity = 255
74+ voldy_sprite .opacity = 255
3975
40- # --- Logica di Gioco ---
4176
4277def esegui_mossa (nome_attaccante , nome_difensore , df_incantesimi , indice_incantesimo ):
78+ """Gestisce il calcolo dei danni, le cure e gli aggiornamenti grafici di una mossa."""
4379 global messaggio , descrizione , gioco_attivo
44-
80+
81+ # Estrazione dati dal DataFrame
4582 danno = float (df_incantesimi [indice_incantesimo , "damage" ])
4683 precisione = float (df_incantesimi [indice_incantesimo , "precision" ])
47- nome_incantesimo = df_incantesimi [indice_incantesimo , ' spell' ].upper ()
48-
84+ nome_incantesimo = df_incantesimi [indice_incantesimo , " spell" ].upper ()
85+
4986 messaggio = f"{ nome_attaccante .upper ()} usa { nome_incantesimo } !"
50-
51- probabilita = random . random ()
52- successo = probabilita < precisione
53-
87+
88+ # Calcolo successo basato sulla precisione
89+ successo = random . random () < precisione
90+
5491 if successo :
55- if danno < 0 : # Cura
92+ if danno < 0 : # Caso incantesimo di Cura
5693 quantita = abs (danno )
57- punti_vita [nome_attaccante ] = min (100 , punti_vita [nome_attaccante ] + quantita )
94+ punti_vita [nome_attaccante ] = min (
95+ 100 , punti_vita [nome_attaccante ] + quantita
96+ )
5897 descrizione = f"Ha recuperato { quantita } PV!"
59- animate (visualizzazione , duration = 0.6 , ** {nome_attaccante : punti_vita [nome_attaccante ]})
60- else : # Attacco
98+ # Anima la barra della vita che sale
99+ animate (
100+ visualizzazione ,
101+ duration = 0.6 ,
102+ ** {nome_attaccante : punti_vita [nome_attaccante ]},
103+ )
104+ else : # Caso incantesimo di Attacco
61105 punti_vita [nome_difensore ] = max (0 , punti_vita [nome_difensore ] - danno )
62106 descrizione = f"Ha inflitto { danno } danni!"
63- # Effetto visivo danno
64- target_sprite = voldy_sprite if nome_difensore == "Voldemort" else harry_sprite
107+ # Attiva effetti visivi sul bersaglio
108+ target_sprite = (
109+ voldy_sprite if nome_difensore == "Voldemort" else harry_sprite
110+ )
65111 flash_danno (target_sprite )
66- animate (visualizzazione , duration = 0.6 , ** {nome_difensore : punti_vita [nome_difensore ]})
112+ # Anima la barra della vita che scende
113+ animate (
114+ visualizzazione ,
115+ duration = 0.6 ,
116+ ** {nome_difensore : punti_vita [nome_difensore ]},
117+ )
67118 else :
119+ # la precisione dell'incantesimo nno è tale da andare a segno
68120 descrizione = f"L'incantesimo è fallito!"
69121
122+ # Controllo condizione di vittoria
70123 if punti_vita [nome_difensore ] <= 0 :
71124 gioco_attivo = False
72125 messaggio = f"{ nome_difensore .upper ()} è esausto!"
73- descrizione = "Il duello è terminato."
126+ descrizione = "Premi SPAZIO per ricominciare."
127+
128+
129+ # Gestione Input e Turni
130+
131+
132+ def on_key_down (key ):
133+ """Rileva la pressione dei tasti, usato qui per il riavvio."""
134+ if not gioco_attivo and key == keys .SPACE :
135+ reset_gioco ()
74136
75- # --- Gestione Turni ---
76137
77138def fase_voldemort ():
78- """Voldemort sceglie un incantesimo casuale e lo lancia ."""
139+ """Gestisce l'intelligenza artificiale di Voldemort ."""
79140 global messaggio , descrizione
80- if not gioco_attivo : return
141+ if not gioco_attivo :
142+ return
81143
82144 opzioni = ottieni_opzioni ("Voldemort" )
83145 indice = random .randint (1 , len (opzioni )) - 1
84146 esegui_mossa ("Voldemort" , "Harry" , opzioni , indice )
85-
86- # Dopo la mossa di Voldemort, aspetta 2 secondi e passa a Harry
147+
148+ # Se Harry è ancora vivo, torna il suo turno dopo 3 secondi
87149 if gioco_attivo :
88- clock .schedule_unique (prepara_harry , 2.0 )
150+ clock .schedule_unique (prepara_harry , 3.0 )
151+
89152
90153def prepara_harry ():
91- """Ripristina l'interfaccia per il turno di Harry ."""
154+ """Ripristina il menu per il turno del giocatore ."""
92155 global messaggio , descrizione , attesa_input
93156 messaggio = "Cosa farà HARRY?"
94157 descrizione = "Scegli un incantesimo..."
95158 attesa_input = True
96159
160+
97161def on_mouse_down (pos ):
162+ """Gestisce il click del mouse sulle opzioni degli incantesimi."""
98163 global attesa_input
99-
164+
100165 if gioco_attivo and attesa_input :
101166 opzioni = ottieni_opzioni ("Harry" )[:4 ]
102167 for i in range (len (opzioni )):
168+ # Calcolo dinamico della posizione dei rettangoli cliccabili (2x2)
103169 x = 40 + (i % 2 ) * 380
104170 y = 440 + (i // 2 ) * 60
105171 if Rect ((x , y ), (350 , 50 )).collidepoint (pos ):
106- # Azione di Harry
107172 attesa_input = False
108173 esegui_mossa ("Harry" , "Voldemort" , opzioni , i )
109-
110- # Se Voldemort è ancora vivo, tocca a lui tra 2 secondi
174+
175+ # Turno di Voldemort dopo 3 secondi se non ha perso
111176 if gioco_attivo :
112- clock .schedule_unique (fase_voldemort , 2.0 )
177+ clock .schedule_unique (fase_voldemort , 3.0 )
178+
179+
180+ # Funzioni di Disegno
113181
114- # --- Funzioni di Disegno ---
115182
116183def draw ():
184+ """Disegna l'interfaccia di gioco ogni frame."""
117185 screen .clear ()
118- # Sfondo Cielo e Prato
119- screen .draw .filled_rect (Rect ((0 , 0 ), (800 , 400 )), (200 , 230 , 255 ))
120- screen .draw .filled_rect (Rect ((0 , 400 ), (800 , 200 )), (120 , 180 , 120 ))
186+ # Disegno ambiente ( Cielo e Prato)
187+ screen .draw .filled_rect (Rect ((0 , 0 ), (800 , 400 )), (200 , 230 , 255 ))
188+ screen .draw .filled_rect (Rect ((0 , 400 ), (800 , 200 )), (120 , 180 , 120 ))
121189
190+ # Disegno personaggi
122191 voldy_sprite .draw ()
123192 harry_sprite .draw ()
124193
194+ # Disegno barre della vita
125195 disegna_barra_stato ("VOLDEMORT" , visualizzazione .Voldemort , 50 , 50 )
126196 disegna_barra_stato ("HARRY" , visualizzazione .Harry , 450 , 250 )
127-
128- # Box dei Dialoghi
197+
198+ # Box dei Dialoghi / Menu (rettangolo scuro in basso)
129199 screen .draw .filled_rect (Rect ((10 , 410 ), (780 , 180 )), (50 , 50 , 60 ))
130200 screen .draw .rect (Rect ((10 , 410 ), (780 , 180 )), "white" )
131201
202+ # Mostra il menu se è il turno del giocatore, altrimenti mostra i messaggi log
132203 if attesa_input and gioco_attivo :
133204 disegna_menu_mosse ()
134205 else :
135206 screen .draw .text (messaggio , (40 , 450 ), fontsize = 40 , color = "white" )
136207 screen .draw .text (descrizione , (40 , 510 ), fontsize = 30 , color = "lightgray" )
137208
209+
138210def disegna_barra_stato (nome , valore , x , y ):
211+ """Disegna un riquadro con nome e barra della salute proporzionale al valore."""
139212 screen .draw .filled_rect (Rect ((x , y ), (300 , 80 )), "white" )
140213 screen .draw .rect (Rect ((x , y ), (300 , 80 )), "black" )
141- screen .draw .text (nome , (x + 20 , y + 15 ), color = "black" , fontsize = 30 )
142- screen .draw .rect (Rect ((x + 100 , y + 45 ), (160 , 15 )), "black" )
143-
214+ screen .draw .text (nome , (x + 20 , y + 15 ), color = "black" , fontsize = 30 )
215+
216+ # Sfondo nero della barra
217+ screen .draw .rect (Rect ((x + 100 , y + 45 ), (160 , 15 )), "black" )
218+
219+ # Calcolo larghezza e colore barra salute
144220 larghezza_barra = (valore / 100 ) * 158
145221 colore = "green" if valore > 50 else "orange" if valore > 20 else "red"
146-
147- if larghezza_barra > 0 :
148- screen .draw .filled_rect (Rect ((x + 101 , y + 46 ), (larghezza_barra , 13 )), colore )
222+
223+ if larghezza_barra > 0 :
224+ screen .draw .filled_rect (Rect ((x + 101 , y + 46 ), (larghezza_barra , 13 )), colore )
225+
149226
150227def disegna_menu_mosse ():
228+ """Disegna le 4 opzioni di incantesimo cliccabili per Harry."""
151229 opzioni = ottieni_opzioni ("Harry" )[:4 ]
152230 for i in range (len (opzioni )):
153- x , y = 40 + (i % 2 ) * 380 , 440 + (i // 2 ) * 60
231+ x , y = 40 + (i % 2 ) * 380 , 440 + (i // 2 ) * 60
154232 screen .draw .rect (Rect ((x , y ), (350 , 50 )), "white" )
155- screen .draw .text (f"> { opzioni [i , 'spell' ].upper ()} " , (x + 20 , y + 15 ), fontsize = 30 )
233+ screen .draw .text (
234+ f"> { opzioni [i , 'spell' ].upper ()} " , (x + 20 , y + 15 ), fontsize = 30
235+ )
236+
156237
157- pgzrun .go ()
238+ # Avvio del gioco
239+ pgzrun .go ()
0 commit comments