/
Jamqwr
/
InvokGame
Обзор
Документация
Войти
/
Jamqwr
/
InvokGame
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
invoker_game.py
274 строки
11 KB
Jamqwr
firstbuild
24 ноя 2025, 13:03
24 ноя 2025, 13:03
6a1eaf7
Код
Авторство
О чём код?
import tkinter as tk import random import time import os # --- КОНФИГУРАЦИЯ ЦВЕТОВ --- BG_COLOR = "#1C1C1C" TEXT_COLOR = "#FFFFFF" ACCENT_COLOR = "#A8A8A8" QUAS_COLOR = "#00BFFF" WEX_COLOR = "#DA70D6" EXORT_COLOR = "#FF8C00" SLOT_EMPTY_COLOR = "#333333" # --- ПОЛНАЯ БИБЛИОТЕКА СКИЛЛОВ (ВСЕ ВАРИАЦИИ) --- # Ключ - точная последовательность сфер, Значение - Скилл SPELL_RECIPES = { # Quas (QQQ) "qqq": "Cold Snap", # Wex (WWW) "www": "EMP", # Exort (EEE) "eee": "Sun Strike", # Ghost Walk (QQW) - 3 вариации "qqw": "Ghost Walk", "qwq": "Ghost Walk", "wqq": "Ghost Walk", # Ice Wall (QQE) - 3 вариации "qqe": "Ice Wall", "qeq": "Ice Wall", "eqq": "Ice Wall", # Tornado (WWQ) - 3 вариации "wwq": "Tornado", "wqw": "Tornado", "qww": "Tornado", # Alacrity (WWE) - 3 вариации "wwe": "Alacrity", "wew": "Alacrity", "eww": "Alacrity", # Forge Spirit (EEQ) - 3 вариации "eeq": "Forge Spirit", "eqe": "Forge Spirit", "qee": "Forge Spirit", # Chaos Meteor (EEW) - 3 вариации "eew": "Chaos Meteor", "ewe": "Chaos Meteor", "wee": "Chaos Meteor", # Deafening Blast (QWE) - 6 вариаций "qwe": "Deafening Blast", "qew": "Deafening Blast", "wqe": "Deafening Blast", "weq": "Deafening Blast", "ewq": "Deafening Blast", "eqw": "Deafening Blast" } # Каноничные рецепты для подсказок (чтобы показывать игроку красивый вариант) HINT_RECIPES = { "Cold Snap": "QQQ", "Ghost Walk": "QQW", "Ice Wall": "QQE", "EMP": "WWW", "Tornado": "WWQ", "Alacrity": "WWE", "Sun Strike": "EEE", "Forge Spirit": "EEQ", "Chaos Meteor": "EEW", "Deafening Blast": "QWE" } class InvokerGame: def __init__(self, root): self.root = root self.root.title("Invoker Training Challenge") self.root.geometry("600x550") # Чуть увеличил высоту self.root.configure(bg=BG_COLOR) self.root.resizable(False, False) # Состояние игры self.current_orbs = [] self.target_spells = [] self.current_spell_index = 0 self.start_time = 0 self.is_playing = False self.highscore = self.load_highscore() # --- ИНТЕРФЕЙС --- # 1. Верхняя панель self.stats_frame = tk.Frame(root, bg=BG_COLOR) self.stats_frame.pack(pady=20, fill="x") self.time_label = tk.Label(self.stats_frame, text="Время: 0.00s", font=("Arial", 16), bg=BG_COLOR, fg="#00FF00") self.time_label.pack(side="left", padx=20) self.score_label = tk.Label(self.stats_frame, text="Прогресс: 0/10", font=("Arial", 16), bg=BG_COLOR, fg=TEXT_COLOR) self.score_label.pack(side="right", padx=20) self.best_time_label = tk.Label(root, text=f"Лучшее время: {self.highscore:.2f}s", font=("Arial", 12), bg=BG_COLOR, fg="#FFD700") self.best_time_label.pack() # 2. Центральная зона self.target_frame = tk.Frame(root, bg=BG_COLOR, pady=10) self.target_frame.pack() self.info_label = tk.Label(self.target_frame, text="Нажми ENTER для старта", font=("Arial", 10), bg=BG_COLOR, fg=ACCENT_COLOR) self.info_label.pack() self.target_spell_label = tk.Label(self.target_frame, text="INVOKER", font=("Arial", 32, "bold"), bg=BG_COLOR, fg=TEXT_COLOR) self.target_spell_label.pack(pady=5) self.recipe_hint_label = tk.Label(self.target_frame, text="", font=("Arial", 14), bg=BG_COLOR, fg="#888888") self.recipe_hint_label.pack() # 3. Слоты сфер self.orbs_frame = tk.Frame(root, bg=BG_COLOR, pady=20) self.orbs_frame.pack() self.orb_canvases = [] for i in range(3): c = tk.Canvas(self.orbs_frame, width=60, height=60, bg=BG_COLOR, highlightthickness=0) c.create_oval(5, 5, 55, 55, fill=SLOT_EMPTY_COLOR, outline=ACCENT_COLOR, width=2, tags="orb") c.pack(side="left", padx=10) self.orb_canvases.append(c) # 4. Кнопки и управление self.controls_frame = tk.Frame(root, bg=BG_COLOR, pady=20) self.controls_frame.pack() self.create_skill_button("Quas (Q)", QUAS_COLOR, lambda: self.add_orb("q")) self.create_skill_button("Wex (W)", WEX_COLOR, lambda: self.add_orb("w")) self.create_skill_button("Exort (E)", EXORT_COLOR, lambda: self.add_orb("e")) self.invoke_btn = tk.Button(root, text="INVOKE (R)", font=("Arial", 14, "bold"), bg="#444", fg="white", width=15, command=self.invoke_spell, relief="raised", bd=3) self.invoke_btn.pack(pady=10) self.start_btn = tk.Button(root, text="НАЧАТЬ (Enter)", font=("Arial", 12), bg="#228B22", fg="white", command=self.handle_enter_action) self.start_btn.pack(side="bottom", pady=20) # --- БИНДЫ --- self.root.bind('<q>', lambda event: self.add_orb("q")) self.root.bind('<w>', lambda event: self.add_orb("w")) self.root.bind('<e>', lambda event: self.add_orb("e")) self.root.bind('<r>', lambda event: self.invoke_spell()) self.root.bind('<Return>', lambda event: self.handle_enter_action()) # Защищенная русская раскладка try: self.root.bind('й', lambda event: self.add_orb("q")) self.root.bind('ц', lambda event: self.add_orb("w")) self.root.bind('у', lambda event: self.add_orb("e")) self.root.bind('к', lambda event: self.invoke_spell()) except: pass self.timer_loop() def create_skill_button(self, text, color, command): btn = tk.Button(self.controls_frame, text=text, font=("Arial", 10, "bold"), bg=color, fg="white", width=10, height=2, command=command) btn.pack(side="left", padx=5) def load_highscore(self): if os.path.exists("highscore.txt"): try: with open("highscore.txt", "r") as f: return float(f.read()) except: return 999.99 return 999.99 def save_highscore(self, time_val): with open("highscore.txt", "w") as f: f.write(str(time_val)) def handle_enter_action(self): if not self.is_playing: self.start_game() def start_game(self): self.is_playing = True self.current_orbs = [] self.update_orbs_ui() self.generate_tasks() self.current_spell_index = 0 self.start_time = time.time() self.start_btn.config(text="ИГРА ИДЕТ...", bg="#555", state="disabled") self.info_label.config(text="СКРАФТИ ЭТОТ СКИЛЛ:", fg=ACCENT_COLOR) self.update_task_ui() def generate_tasks(self): # Берем уникальные названия скиллов unique_spells = list(HINT_RECIPES.keys()) self.target_spells = [random.choice(unique_spells) for _ in range(10)] def add_orb(self, orb_type): if not self.is_playing: return self.current_orbs.append(orb_type) if len(self.current_orbs) > 3: self.current_orbs.pop(0) self.update_orbs_ui() def update_orbs_ui(self): color_map = {"q": QUAS_COLOR, "w": WEX_COLOR, "e": EXORT_COLOR} for i, canvas in enumerate(self.orb_canvases): canvas.delete("orb") if i < len(self.current_orbs): orb = self.current_orbs[i] canvas.create_oval(5, 5, 55, 55, fill=color_map[orb], outline="white", width=2, tags="orb") canvas.create_text(30, 30, text=orb.upper(), font=("Arial", 20, "bold"), fill="white", tags="orb") else: canvas.create_oval(5, 5, 55, 55, fill=SLOT_EMPTY_COLOR, outline=ACCENT_COLOR, width=2, tags="orb") def invoke_spell(self): if not self.is_playing: return if len(self.current_orbs) < 3: return # Ключевое изменение: НЕ сортируем, берем как есть current_recipe = "".join(self.current_orbs) # Ищем в полном словаре вариаций casted_spell = SPELL_RECIPES.get(current_recipe, "Unknown") target_spell = self.target_spells[self.current_spell_index] if casted_spell == target_spell: self.flash_feedback("green") self.current_spell_index += 1 if self.current_spell_index >= len(self.target_spells): self.game_over() else: self.update_task_ui() else: self.flash_feedback("red") def update_task_ui(self): target = self.target_spells[self.current_spell_index] self.target_spell_label.config(text=target, fg="#00BFFF") self.score_label.config(text=f"Прогресс: {self.current_spell_index}/10") # Подсказку берем из "красивого" словаря recipe_hint = HINT_RECIPES[target] self.recipe_hint_label.config(text=f"Рецепт: {recipe_hint}") def flash_feedback(self, color): original_bg = BG_COLOR flash_color = "#003300" if color == "green" else "#330000" self.root.configure(bg=flash_color) self.target_frame.configure(bg=flash_color) self.root.after(100, lambda: self.root.configure(bg=original_bg)) self.root.after(100, lambda: self.target_frame.configure(bg=original_bg)) def timer_loop(self): if self.is_playing: elapsed = time.time() - self.start_time self.time_label.config(text=f"Время: {elapsed:.2f}s") self.root.after(50, self.timer_loop) def game_over(self): self.is_playing = False final_time = time.time() - self.start_time is_new = False if final_time < self.highscore: self.highscore = final_time self.save_highscore(final_time) is_new = True self.best_time_label.config(text=f"Лучшее время: {self.highscore:.2f}s") self.start_btn.config(text="ENTER ЧТОБЫ ПОВТОРИТЬ", bg="#228B22", state="normal") if is_new: self.info_label.config(text="НОВЫЙ РЕКОРД!", fg="#FFFF00") self.target_spell_label.config(text=f"{final_time:.2f} сек", fg="#FFFF00") else: self.info_label.config(text="ИГРА ОКОНЧЕНА", fg=TEXT_COLOR) self.target_spell_label.config(text=f"{final_time:.2f} сек", fg=TEXT_COLOR) self.recipe_hint_label.config(text="Нажми Enter для рестарта") if __name__ == "__main__": root = tk.Tk() game = InvokerGame(root) root.mainloop()