Skip to content

Commit 0739902

Browse files
authored
Create Text-Rpg-Gui.py
1 parent cac92c6 commit 0739902

1 file changed

Lines changed: 300 additions & 0 deletions

File tree

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
import tkinter as tk
2+
from tkinter import messagebox
3+
import ttkbootstrap as ttk
4+
from ttkbootstrap.constants import *
5+
import random
6+
7+
# ----- Game Logic -----
8+
class Player:
9+
def __init__(self, name):
10+
self.name = name
11+
self.hp = 100
12+
self.max_hp = 100
13+
self.level = 1
14+
self.exp = 0
15+
self.items = {"Potion": 2, "Elixir": 1, "Bomb": 1}
16+
self.status_effects = {}
17+
18+
def gain_exp(self, amount):
19+
self.exp += amount
20+
if self.exp >= 100:
21+
self.level_up()
22+
23+
def level_up(self):
24+
self.level += 1
25+
self.max_hp += 20
26+
self.hp = self.max_hp
27+
self.exp = 0
28+
messagebox.showinfo("Level Up!", f"{self.name} reached level {self.level}!")
29+
30+
def use_item(self, item_name, target_enemy=None):
31+
if self.items.get(item_name, 0) > 0:
32+
if item_name == "Potion":
33+
heal_amount = 50
34+
self.hp = min(self.max_hp, self.hp + heal_amount)
35+
self.items[item_name] -= 1
36+
return heal_amount, f"{self.name} used a Potion and restored {heal_amount} HP!"
37+
elif item_name == "Elixir":
38+
heal_amount = 100
39+
self.hp = min(self.max_hp, self.hp + heal_amount)
40+
self.items[item_name] -= 1
41+
return heal_amount, f"{self.name} used an Elixir and restored {heal_amount} HP!"
42+
elif item_name == "Bomb" and target_enemy:
43+
damage = 50
44+
target_enemy.hp -= damage
45+
target_enemy.add_status('burn', 2)
46+
self.items[item_name] -= 1
47+
return -damage, f"{self.name} used a Bomb on {target_enemy.name} for {damage} damage and inflicted burn!"
48+
return 0, f"No {item_name}s left!"
49+
50+
def add_status(self, status_name, duration):
51+
self.status_effects[status_name] = duration
52+
53+
def apply_statuses(self):
54+
total_damage = 0
55+
if 'poison' in self.status_effects:
56+
dmg = 5
57+
self.hp -= dmg
58+
total_damage += dmg
59+
self.status_effects['poison'] -= 1
60+
if self.status_effects['poison'] <= 0:
61+
del self.status_effects['poison']
62+
return total_damage
63+
64+
class Enemy:
65+
def __init__(self, name, hp, exp_reward):
66+
self.name = name
67+
self.hp = hp
68+
self.max_hp = hp
69+
self.exp_reward = exp_reward
70+
self.status_effects = {}
71+
72+
def add_status(self, status_name, duration):
73+
self.status_effects[status_name] = duration
74+
75+
def apply_statuses(self):
76+
total_damage = 0
77+
if 'burn' in self.status_effects:
78+
dmg = 10
79+
self.hp -= dmg
80+
total_damage += dmg
81+
self.status_effects['burn'] -= 1
82+
if self.status_effects['burn'] <= 0:
83+
del self.status_effects['burn']
84+
return total_damage
85+
86+
# ----- Game Engine -----
87+
class GameEngine:
88+
def __init__(self, root):
89+
self.root = root
90+
self.root.title("Text-Based RPG")
91+
self.style = ttk.Style(theme="cosmo")
92+
93+
self.player = None
94+
self.current_enemy = None
95+
96+
self.frame = ttk.Frame(root, padding=20)
97+
self.frame.pack(fill=BOTH, expand=YES)
98+
99+
self.label = ttk.Label(self.frame, text="Enter your hero's name:")
100+
self.label.pack(pady=5)
101+
102+
self.entry = ttk.Entry(self.frame)
103+
self.entry.pack(pady=5)
104+
105+
self.start_button = ttk.Button(self.frame, text="Start Adventure", command=self.start_game)
106+
self.start_button.pack(pady=10)
107+
108+
# HP bars
109+
self.player_hp_bar = ttk.Progressbar(self.frame, length=300, maximum=100)
110+
self.enemy_hp_bar = ttk.Progressbar(self.frame, length=300, maximum=100)
111+
112+
# Status labels
113+
self.player_status_label = ttk.Label(self.frame, text="Player Status: None")
114+
self.enemy_status_label = ttk.Label(self.frame, text="Enemy Status: None")
115+
116+
# Canvas for attack/heal animations
117+
self.animation_canvas = tk.Canvas(self.frame, width=300, height=50, bg="white")
118+
self.animation_canvas.pack(pady=5)
119+
120+
self.text_area = tk.Text(self.frame, height=10, state=DISABLED)
121+
self.text_area.pack(pady=10, fill=BOTH, expand=YES)
122+
123+
self.action_frame = ttk.Frame(self.frame)
124+
self.action_frame.pack(pady=10)
125+
126+
def start_game(self):
127+
name = self.entry.get().strip()
128+
if not name:
129+
messagebox.showwarning("Input Error", "Please enter a valid name.")
130+
return
131+
132+
self.player = Player(name)
133+
self.entry.destroy()
134+
self.start_button.destroy()
135+
self.label.config(text=f"Welcome, {name}! Choose your action:")
136+
137+
# Show HP bars and status labels
138+
self.player_hp_bar.pack(pady=5)
139+
self.enemy_hp_bar.pack(pady=5)
140+
self.player_status_label.pack()
141+
self.enemy_status_label.pack()
142+
143+
self.show_main_actions()
144+
self.update_bars()
145+
146+
def show_main_actions(self):
147+
for widget in self.action_frame.winfo_children():
148+
widget.destroy()
149+
ttk.Button(self.action_frame, text="Explore", command=self.explore).pack(side=LEFT, padx=5)
150+
ttk.Button(self.action_frame, text="Show Stats", command=self.show_stats).pack(side=LEFT, padx=5)
151+
ttk.Button(self.action_frame, text="Quit", command=self.root.quit).pack(side=LEFT, padx=5)
152+
153+
def explore(self):
154+
enemies = [Enemy("Goblin", 50, 20), Enemy("Orc", 80, 40), Enemy("Dragon", 150, 100)]
155+
self.current_enemy = random.choice(enemies)
156+
self.log(f"You encountered a {self.current_enemy.name} with {self.current_enemy.hp} HP!")
157+
self.enemy_hp_bar['maximum'] = self.current_enemy.max_hp
158+
self.enemy_hp_bar['value'] = self.current_enemy.hp
159+
self.show_combat_menu()
160+
self.update_status_labels()
161+
162+
def show_combat_menu(self):
163+
for widget in self.action_frame.winfo_children():
164+
widget.destroy()
165+
ttk.Button(self.action_frame, text="Attack", command=self.attack).pack(side=LEFT, padx=5)
166+
ttk.Button(self.action_frame, text="Defend", command=self.defend).pack(side=LEFT, padx=5)
167+
ttk.Button(self.action_frame, text="Use Item", command=self.show_inventory).pack(side=LEFT, padx=5)
168+
ttk.Button(self.action_frame, text="Run", command=self.run_away).pack(side=LEFT, padx=5)
169+
170+
def attack(self):
171+
damage = random.randint(15, 30)
172+
self.animate_attack(target='enemy')
173+
self.current_enemy.hp -= damage
174+
self.log(f"You attack {self.current_enemy.name} for {damage} damage.")
175+
self.apply_status_effects()
176+
self.update_bars()
177+
self.check_battle_end()
178+
self.enemy_turn()
179+
180+
def defend(self):
181+
self.log(f"{self.player.name} braces for the next attack, reducing damage taken!")
182+
self.apply_status_effects()
183+
self.update_bars()
184+
self.enemy_turn(defending=True)
185+
186+
def show_inventory(self):
187+
inv_window = tk.Toplevel(self.root)
188+
inv_window.title("Inventory")
189+
for item, count in self.player.items.items():
190+
if count > 0:
191+
def use_item_closure(item_name=item):
192+
amount, result = self.player.use_item(item_name, target_enemy=self.current_enemy)
193+
if amount > 0:
194+
self.animate_heal(amount)
195+
elif amount < 0:
196+
self.animate_attack(target='enemy')
197+
self.log(result)
198+
inv_window.destroy()
199+
self.apply_status_effects()
200+
self.update_bars()
201+
self.check_battle_end()
202+
self.enemy_turn()
203+
ttk.Button(inv_window, text=f"{item} x{count}", command=use_item_closure).pack(pady=5)
204+
205+
def animate_attack(self, target='enemy'):
206+
bar = self.enemy_hp_bar if target=='enemy' else self.player_hp_bar
207+
original_color = bar.cget('style')
208+
flash_color = 'danger.Horizontal.TProgressbar'
209+
self.style.configure(flash_color, troughcolor='white', background='red')
210+
bar['style'] = flash_color
211+
self.root.after(200, lambda: bar.configure(style=original_color))
212+
213+
def animate_heal(self, amount):
214+
bar = self.player_hp_bar
215+
original_color = bar.cget('style')
216+
flash_color = 'success.Horizontal.TProgressbar'
217+
self.style.configure(flash_color, troughcolor='white', background='green')
218+
bar['style'] = flash_color
219+
self.root.after(200, lambda: bar.configure(style=original_color))
220+
221+
def run_away(self):
222+
success = random.random() > 0.3
223+
if success:
224+
self.log("You successfully ran away!")
225+
self.show_main_actions()
226+
else:
227+
self.log("Failed to run away!")
228+
self.apply_status_effects()
229+
self.update_bars()
230+
self.enemy_turn()
231+
232+
def enemy_turn(self, defending=False):
233+
if self.current_enemy.hp <= 0:
234+
return
235+
damage = random.randint(10, 25)
236+
if defending:
237+
damage //= 2
238+
self.player.hp -= damage
239+
self.animate_attack(target='player')
240+
self.log(f"{self.current_enemy.name} attacks you for {damage} damage.")
241+
self.apply_status_effects()
242+
self.update_bars()
243+
self.check_player_defeat()
244+
245+
def apply_status_effects(self):
246+
player_damage = self.player.apply_statuses()
247+
enemy_damage = self.current_enemy.apply_statuses() if self.current_enemy else 0
248+
if player_damage > 0:
249+
self.animate_attack(target='player')
250+
self.log(f"{self.player.name} took {player_damage} damage from status effects!")
251+
if enemy_damage > 0:
252+
self.animate_attack(target='enemy')
253+
self.log(f"{self.current_enemy.name} took {enemy_damage} damage from status effects!")
254+
self.update_status_labels()
255+
256+
def update_bars(self):
257+
if self.player:
258+
self.player_hp_bar['maximum'] = self.player.max_hp
259+
self.player_hp_bar['value'] = max(0, self.player.hp)
260+
if self.current_enemy:
261+
self.enemy_hp_bar['maximum'] = self.current_enemy.max_hp
262+
self.enemy_hp_bar['value'] = max(0, self.current_enemy.hp)
263+
264+
def update_status_labels(self):
265+
player_status = ', '.join([f"{k}({v})" for k,v in self.player.status_effects.items()]) or 'None'
266+
enemy_status = ', '.join([f"{k}({v})" for k,v in self.current_enemy.status_effects.items()]) if self.current_enemy else 'None'
267+
self.player_status_label.config(text=f"Player Status: {player_status}")
268+
self.enemy_status_label.config(text=f"Enemy Status: {enemy_status}")
269+
270+
def show_stats(self):
271+
items_list = ', '.join([f"{k} x{v}" for k, v in self.player.items.items() if v > 0])
272+
status_list = ', '.join([f"{k} ({v} turns)" for k, v in self.player.status_effects.items()])
273+
status_text = status_list if status_list else 'None'
274+
self.log(f"Name: {self.player.name} | HP: {self.player.hp}/{self.player.max_hp} | Level: {self.player.level} | EXP: {self.player.exp} | Items: {items_list} | Status: {status_text}")
275+
276+
def check_battle_end(self):
277+
if self.current_enemy and self.current_enemy.hp <= 0:
278+
self.log(f"You defeated {self.current_enemy.name}!")
279+
self.player.gain_exp(self.current_enemy.exp_reward)
280+
self.current_enemy = None
281+
self.show_main_actions()
282+
self.update_bars()
283+
284+
def check_player_defeat(self):
285+
if self.player.hp <= 0:
286+
self.log("You were defeated! Game Over.")
287+
messagebox.showinfo("Game Over", "You have fallen in battle.")
288+
self.root.quit()
289+
290+
def log(self, message):
291+
self.text_area.config(state=NORMAL)
292+
self.text_area.insert(END, message + "\n")
293+
self.text_area.see(END)
294+
self.text_area.config(state=DISABLED)
295+
296+
# ----- Main Application -----
297+
if __name__ == "__main__":
298+
root = ttk.Window(themename="cosmo")
299+
app = GameEngine(root)
300+
root.mainloop()

0 commit comments

Comments
 (0)