Skip to content

Commit a215b81

Browse files
committed
add harry potter ganme
1 parent 0aa52d4 commit a215b81

File tree

2 files changed

+105
-103
lines changed

2 files changed

+105
-103
lines changed

game11/harry_potter.py

Lines changed: 97 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -3,149 +3,151 @@
33
import pgzrun
44
from types import SimpleNamespace
55

6-
# --- Settings ---
76
WIDTH = 800
87
HEIGHT = 600
9-
TITLE = "Wizarding Duel: Turn-Based Strategy"
8+
TITLE = "Wizarding Duel: The Final Battle"
109

1110
# --- State ---
1211
hp = {"Harry": 100, "Voldemort": 100}
1312
display = SimpleNamespace(Harry=100, Voldemort=100)
1413

14+
# Sprites (Ensure harry.png and voldemort.png are in the 'images' folder)
15+
harry_sprite = Actor('harry', (200, 320))
16+
voldy_sprite = Actor('voldemort', (600, 150))
17+
1518
message = "A wild VOLDEMORT appeared!"
1619
sub_message = "What will HARRY do?"
17-
current_turn = "Harry" # Who is currently attacking
18-
waiting_for_input = True # Controls if buttons are visible
20+
waiting_for_input = True
1921
game_active = True
2022

2123
# --- Load Data ---
22-
spells_df = pl.read_csv("spells.csv")
24+
spells_df = pl.read_csv(r"C:\Users\alema\Desktop\pythonbiella\LearningPythonWithGames\game11\spells.csv")
2325

2426
def get_options(character):
25-
return spells_df.filter(pl.col("character") == character).to_dicts()
27+
return spells_df.filter(pl.col("character") == character)
2628

27-
# --- Battle Logic ---
29+
# --- Visual Effects ---
2830

29-
def player_choice(spell_data):
30-
"""Triggered when Harry clicks a button."""
31-
global waiting_for_input, message, sub_message
32-
33-
waiting_for_input = False
34-
execute_move("Harry", "Voldemort", spell_data)
35-
36-
# If Voldemort survived, schedule his turn in 2 seconds
37-
if game_active:
38-
clock.schedule_unique(voldemort_turn, 2.0)
31+
def flash_hurt(sprite):
32+
"""Blinks the sprite and shakes it slightly."""
33+
original_x = sprite.x
34+
# Quick shake
35+
animate(sprite, duration=0.1, x=original_x + 10, tween='bounce_end')
36+
# Blink
37+
for i in range(3):
38+
clock.schedule_unique(lambda: setattr(sprite, 'opacity', 0), i * 0.2)
39+
clock.schedule_unique(lambda: setattr(sprite, 'opacity', 255), i * 0.2 + 0.1)
40+
# Reset position
41+
clock.schedule_unique(lambda: setattr(sprite, 'x', original_x), 0.3)
3942

40-
def voldemort_turn():
41-
"""Triggered automatically after Harry's turn."""
42-
global message, sub_message, waiting_for_input
43-
44-
if not game_active: return
43+
# --- Logic Core ---
4544

46-
choices = get_options("Voldemort")
47-
spell = random.choice(choices)
48-
49-
execute_move("Voldemort", "Harry", spell)
50-
51-
# After Voldemort attacks, give Harry control back in 1.5 seconds
52-
if game_active:
53-
clock.schedule_unique(reset_to_player, 1.5)
54-
55-
def execute_move(attacker, defender, spell_data):
45+
def execute_move(attacker_name, defender_name, spell_df, spell_index):
5646
global message, sub_message, game_active
5747

58-
raw_damage = float(spell_data["damage"])
59-
60-
# --- HEALING LOGIC ---
61-
if raw_damage < 0:
62-
# It's a heal! Target is the attacker, not the defender
63-
heal_amount = abs(raw_damage)
64-
hp[attacker] = min(100, hp[attacker] + heal_amount) # Cap at 100
65-
66-
message = f"{attacker.upper()} used {spell_data['spell'].upper()}!"
67-
sub_message = f"It recovered {heal_amount} HP!"
68-
69-
# Animate the attacker's bar
70-
if attacker == "Harry":
71-
animate(display, duration=0.6, Harry=hp["Harry"])
72-
else:
73-
animate(display, duration=0.6, Voldemort=hp["Voldemort"])
74-
75-
# --- ATTACK LOGIC ---
48+
dmg = float(spell_df[spell_index, "damage"])
49+
precision = float(spell_df[spell_index, "precision"])
50+
message = f"{attacker_name.upper()} used {spell_df[spell_index, 'spell'].upper()}!"
51+
a = random.random()
52+
spell_successful = a < precision
53+
print(a, precision)
54+
if spell_successful:
55+
if dmg < 0: # Healing
56+
amt = abs(dmg)
57+
hp[attacker_name] = min(100, hp[attacker_name] + amt)
58+
sub_message = f"It recovered {amt} HP!"
59+
animate(display, duration=0.6, **{attacker_name: hp[attacker_name]})
60+
else: # Attacking
61+
hp[defender_name] = max(0, hp[defender_name] - dmg)
62+
sub_message = f"It dealt {dmg} damage!"
63+
# Visual hurt effect
64+
target_sprite = voldy_sprite if defender_name == "Voldemort" else harry_sprite
65+
flash_hurt(target_sprite)
66+
animate(display, duration=0.6, **{defender_name: hp[defender_name]})
7667
else:
77-
hp[defender] = max(0, hp[defender] - raw_damage)
78-
message = f"{attacker.upper()} used {spell_data['spell'].upper()}!"
79-
sub_message = f"It dealt {raw_damage} damage!"
80-
81-
# Animate the defender's bar
82-
if defender == "Harry":
83-
animate(display, duration=0.6, Harry=hp["Harry"])
84-
else:
85-
animate(display, duration=0.6, Voldemort=hp["Voldemort"])
86-
87-
# Check for win/loss (only matters if damage was dealt)
88-
if hp[defender] <= 0:
68+
sub_message = f"The spell did not work!"
69+
70+
if hp[defender_name] <= 0:
8971
game_active = False
90-
message = f"{defender.upper()} fainted!"
91-
sub_message = f"{attacker.upper()} is the winner!"
72+
message = f"{defender_name.upper()} fainted!"
73+
sub_message = "The duel is over."
74+
75+
# --- Turn Handlers ---
76+
77+
def voldemort_phase():
78+
"""Voldemort picks a random spell and casts it."""
79+
global message, sub_message
80+
if not game_active: return
81+
82+
options = get_options("Voldemort")
83+
spell_index = random.randint(1, len(options)) - 1
84+
execute_move("Voldemort", "Harry", options, spell_index)
85+
86+
# After Voldemort moves, wait 2 seconds then let Harry play
87+
if game_active:
88+
clock.schedule_unique(ready_harry, 2.0)
9289

93-
def reset_to_player():
90+
def ready_harry():
91+
"""Resets the UI so Harry can choose a spell."""
9492
global message, sub_message, waiting_for_input
9593
message = "What will HARRY do?"
96-
sub_message = "Choose a spell to cast!"
94+
sub_message = "Select a spell..."
9795
waiting_for_input = True
9896

97+
def on_mouse_down(pos):
98+
global waiting_for_input
99+
100+
if game_active and waiting_for_input:
101+
options = get_options("Harry")[:4]
102+
for i in range(len(options)):
103+
x = 40 + (i % 2) * 380
104+
y = 440 + (i // 2) * 60
105+
if Rect((x, y), (350, 50)).collidepoint(pos):
106+
# Harry's action
107+
waiting_for_input = False
108+
execute_move("Harry", "Voldemort", options, i)
109+
110+
# If Voldemort is still alive, he takes his turn in 2 seconds
111+
if game_active:
112+
clock.schedule_unique(voldemort_phase, 2.0)
113+
99114
# --- Draw Functions ---
100115

101116
def draw():
117+
screen.clear()
102118
screen.draw.filled_rect(Rect((0, 0), (800, 400)), (200, 230, 255))
103119
screen.draw.filled_rect(Rect((0, 400), (800, 200)), (120, 180, 120))
104120

105-
# Status Boxes
121+
voldy_sprite.draw()
122+
harry_sprite.draw()
123+
106124
draw_status_box("VOLDEMORT", display.Voldemort, 50, 50)
107-
draw_status_box("HARRY", display.Harry, 450, 300)
125+
draw_status_box("HARRY", display.Harry, 450, 250)
108126

109-
# UI Box
127+
# Dialogue Box
110128
screen.draw.filled_rect(Rect((10, 410), (780, 180)), (50, 50, 60))
111129
screen.draw.rect(Rect((10, 410), (780, 180)), "white")
112130

113131
if waiting_for_input and game_active:
114132
draw_move_menu()
115133
else:
116-
# Show text messages during animations or enemy turn
117134
screen.draw.text(message, (40, 450), fontsize=40, color="white")
118135
screen.draw.text(sub_message, (40, 510), fontsize=30, color="lightgray")
119136

120-
def draw_status_box(name, current_hp, x, y):
137+
def draw_status_box(name, val, x, y):
121138
screen.draw.filled_rect(Rect((x, y), (300, 80)), "white")
122139
screen.draw.rect(Rect((x, y), (300, 80)), "black")
123-
screen.draw.text(name, (x + 20, y + 15), color="black", fontsize=30)
124-
# HP Bar Border
125-
screen.draw.rect(Rect((x + 100, y + 45), (160, 15)), "black")
126-
# Fill
127-
bar_width = (current_hp / 100) * 158
128-
color = "green" if current_hp > 50 else "orange" if current_hp > 20 else "red"
129-
if bar_width > 0:
130-
screen.draw.filled_rect(Rect((x + 101, y + 46), (bar_width, 13)), color)
140+
screen.draw.text(name, (x+20, y+15), color="black", fontsize=30)
141+
screen.draw.rect(Rect((x+100, y+45), (160, 15)), "black")
142+
bw = (val / 100) * 158
143+
c = "green" if val > 50 else "orange" if val > 20 else "red"
144+
if bw > 0: screen.draw.filled_rect(Rect((x+101, y+46), (bw, 13)), c)
131145

132146
def draw_move_menu():
133-
options = get_options("Harry")[:4]
134-
for i, spell in enumerate(options):
135-
x = 40 + (i % 2) * 380
136-
y = 440 + (i // 2) * 60
147+
opts = get_options("Harry")[:4]
148+
for i in range(len(opts)):
149+
x, y = 40 + (i%2)*380, 440 + (i//2)*60
137150
screen.draw.rect(Rect((x, y), (350, 50)), "white")
138-
screen.draw.text(f"> {spell['spell'].upper()}", (x + 20, y + 15), fontsize=30)
139-
140-
# --- Input ---
141-
142-
def on_mouse_down(pos):
143-
if game_active and waiting_for_input:
144-
options = get_options("Harry")[:4]
145-
for i in range(len(options)):
146-
x = 40 + (i % 2) * 380
147-
y = 440 + (i // 2) * 60
148-
if Rect((x, y), (350, 50)).collidepoint(pos):
149-
player_choice(options[i])
151+
screen.draw.text(f"> {opts[i, 'spell'].upper()}", (x+20, y+15), fontsize=30)
150152

151153
pgzrun.go()

game11/spells.csv

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
character,spell,damage
2-
Harry,Expelliarmus,10
3-
Harry,Stupefy,15
4-
Harry,Expecto Patronum,20
5-
Harry, Epsikey, -25
6-
Voldemort,Crucio,15
7-
Voldemort,Imperio,20
8-
Voldemort,Avada Kedavra,40
1+
character,spell,damage,precision
2+
Harry,Expelliarmus,10,1
3+
Harry,Stupefy,15,1
4+
Harry,Expecto Patronum,20,1
5+
Harry, Epsikey, -25,1
6+
Voldemort,Crucio,15,0.7
7+
Voldemort,Imperio,20,0.6
8+
Voldemort,Avada Kedavra,40,0.3

0 commit comments

Comments
 (0)