
خب برای این پروژه وسایلی که نیاز دارید :
برنامه پایتون
کتابخانه tkinter
کتابخانه json
کتابخانه datetime
کتابخانه random
کتابخانه os
کتابخانه math

کتابخانه های لازم را نصب کنید و کد زیر را دخل آن وارد کنید.
import tkinter as tk from tkinter import ttk # For themed widgets like Notebook (tabs) import json import datetime import random import os import math # For ceiling function SETTINGS_FILE = "hamster_combat_settings.json" # --- Initial Data --- INITIAL_UPGRADES = { "tap_boost": {"name": "Tap Boost", "description": "Increases balance per tap", "base_cost": 100, "cost_multiplier": 1.15, "tap_increase": 1, "level": 0, "icon": "⚡"}, "hourly_profit_boost": {"name": "Hourly Profit Boost", "description": "Increases profit per hour", "base_cost": 500, "cost_multiplier": 1.2, "hourly_profit": 10, "level": 0, "icon": "💰"}, "cost_reduction": {"name": "Cost Reduction", "description": "Reduces upgrade costs", "base_cost": 1000, "cost_multiplier": 1.3, "cost_reduction_percent": 0.05, "level": 0, "icon": "📉"}, # 5% reduction "special_card_chance": {"name": "Special Card Chance", "description": "Increases chance of special cards", "base_cost": 2000, "cost_multiplier": 1.25, "special_card_chance_boost": 0.02, "level": 0, "icon": "❓"} # 2% boost } SPECIAL_CARDS = { "double_tap": {"name": "Double Tap", "duration": 60, "effect": lambda balance, tap_value: (balance + tap_value * 2, tap_value * 2), "description": "Tap value doubled", "icon": "💥"}, "hourly_boost_x5": {"name": "Hourly Boost x5", "duration": 120, "effect": lambda profit: profit * 5, "description": "Hourly profit x5", "icon": "🚀"}, "free_upgrade": {"name": "Free Upgrade", "duration": 10, "effect": lambda: True, "description": "Next upgrade is free", "icon": "🎁"} } # --- Colors and Fonts --- BG_COLOR = '#f0e6d2' FRAME_COLOR = '#e8dcc2' BUTTON_COLOR = '#a08a7a' BUTTON_HOVER_COLOR = '#8a7a6a' TEXT_COLOR_DARK = '#3a2a1a' TEXT_COLOR_MEDIUM = '#5a4a3a' FONT_LARGE_BOLD = ('Arial', 24, 'bold') FONT_MEDIUM_BOLD = ('Arial', 18, 'bold') FONT_MEDIUM = ('Arial', 16) FONT_SMALL_BOLD = ('Arial', 14, 'bold') FONT_SMALL = ('Arial', 12) FONT_TINY_ITALIC = ('Arial', 10, 'italic') # --- Game Class --- class HamsterCombatGame: def __init__(self, master): self.master = master self.master.title("Hamster Combat Sim") self.master.geometry("900x700") # Adjusted size for better layout self.master.configure(bg=BG_COLOR) # --- Game State Variables --- self.balance = tk.IntVar(value=0) self.hourly_profit = tk.IntVar(value=0) self.tap_value = tk.IntVar(value=1) self.current_cost_multiplier = tk.DoubleVar(value=1.0) self.special_card_chance_boost = tk.DoubleVar(value=0.0) self.active_special_card = None self.special_card_end_time = None self.last_hourly_profit_time = datetime.datetime.now() self.original_hourly_profit_for_boost = 0 # To store profit before x5 boost self.upgrades = self.load_settings() self.save_settings_on_exit() self.create_main_layout() self.update_display() self.add_hourly_profit_periodically() self.check_special_cards() self.trigger_random_special_card() # Start checking for special cards self.auto_save() def create_main_layout(self): # --- Main Notebook (Tabbed Interface) --- self.notebook = ttk.Notebook(self.master) self.notebook.pack(pady=10, padx=10, expand=True, fill='both') # --- Frame Colors for Notebook --- style = ttk.Style() style.configure("TNotebook", background=BG_COLOR, borderwidth=0) style.map("TNotebook", background=[("selected", BG_COLOR)]) # Make selected tab background match style.configure("TNotebook.Tab", padding=[10, 5], font=FONT_SMALL_BOLD, background=FRAME_COLOR, foreground=TEXT_COLOR_MEDIUM) style.map("TNotebook.Tab", background=[("selected", BG_COLOR)], foreground=[("selected", TEXT_COLOR_DARK)]) # --- Create individual tabs --- self.home_tab = ttk.Frame(self.notebook, padding=15, style="TFrame") self.upgrades_tab = ttk.Frame(self.notebook, padding=15, style="TFrame") self.mines_tab = ttk.Frame(self.notebook, padding=15, style="TFrame") # Placeholder for future expansion self.notebook.add(self.home_tab, text=' 🏠 Home ') self.notebook.add(self.upgrades_tab, text=' 🛠️ Upgrades ') self.notebook.add(self.mines_tab, text=' ⛏️ Mines ') # --- Populate Tabs --- self.create_home_tab_widgets() self.create_upgrades_tab_widgets() # self.create_mines_tab_widgets() # Call if mines tab is implemented # --- Home Tab --- def create_home_tab_widgets(self): home_frame = self.home_tab # Top Panel: Balance and Profit Display top_panel = tk.Frame(home_frame, bg=FRAME_COLOR, pady=15, relief=tk.RIDGE, borderwidth=2) top_panel.pack(fill=tk.X, pady=(0, 20)) tk.Label(top_panel, text="Hamster Coin:", font=FONT_LARGE_BOLD, bg=FRAME_COLOR, fg=TEXT_COLOR_DARK).pack(pady=(0, 5)) self.balance_label = tk.Label(top_panel, textvariable=self.balance, font=('Arial', 48, 'bold'), bg=FRAME_COLOR, fg=TEXT_COLOR_DARK) self.balance_label.pack(pady=5) self.profit_label = tk.Label(home_frame, text="", font=FONT_MEDIUM, bg=BG_COLOR, fg=TEXT_COLOR_MEDIUM) self.profit_label.pack(pady=5) # Central Area: Click Button click_area = tk.Frame(home_frame, bg=BG_COLOR) click_area.pack(pady=30, expand=True) self.click_button = tk.Button(click_area, text="Click Me!", font=('Impact', 40), bg=BUTTON_COLOR, fg='white', activebackground=BUTTON_HOVER_COLOR, activeforeground='white', command=self.increase_balance_by_tap, relief=tk.FLAT, borderwidth=0, # Flat button style padx=30, pady=20, width=10) # Increased padding for button size self.click_button.pack(pady=20) # Add a subtle visual effect on hover (optional, requires more advanced binding) # Special Card Info Display self.special_card_label = tk.Label(home_frame, text="", font=FONT_MEDIUM_BOLD, bg=BG_COLOR, fg='#d85000') self.special_card_label.pack(pady=10) # --- Upgrades Tab --- def create_upgrades_tab_widgets(self): upgrade_frame = self.upgrades_tab # Canvas for scrollable upgrades self.upgrade_canvas = tk.Canvas(upgrade_frame, bg=BG_COLOR, highlightthickness=0) self.upgrade_scrollbar = ttk.Scrollbar(upgrade_frame, orient="vertical", command=self.upgrade_canvas.yview) self.scrollable_upgrade_frame = tk.Frame(self.upgrade_canvas, bg=BG_COLOR) self.upgrade_scrollbar.pack(side="right", fill="y") self.upgrade_canvas.pack(side="left", fill="both", expand=True) self.upgrade_canvas.configure(yscrollcommand=self.upgrade_scrollbar.set) self.upgrade_canvas.create_window((0, 0), window=self.scrollable_upgrade_frame, anchor="nw") self.scrollable_upgrade_frame.bind("<Configure>", lambda e: self.upgrade_canvas.configure(scrollregion=self.upgrade_canvas.bbox("all"))) self.load_upgrade_buttons() def load_upgrade_buttons(self): # Clear previous buttons if any for widget in self.scrollable_upgrade_frame.winfo_children(): widget.destroy() row_num = 0 for key, upgrade_data in sorted(self.upgrades.items()): # Sort for consistent order frame = tk.Frame(self.scrollable_upgrade_frame, bg=FRAME_COLOR, relief=tk.RAISED, borderwidth=2, padx=10, pady=8) frame.grid(row=row_num, column=0, sticky="ew", padx=5, pady=5) # Icon and Name icon = upgrade_data.get("icon", "") tk.Label(frame, text=f"{icon} {upgrade_data['name']} (Lv. {upgrade_data['level']})", font=FONT_SMALL_BOLD, bg=FRAME_COLOR, fg=TEXT_COLOR_DARK, anchor='w').grid(row=0, column=0, sticky="w", padx=(5, 0)) # Description desc = upgrade_data.get('description', '') tk.Label(frame, text=desc, font=FONT_TINY_ITALIC, bg=FRAME_COLOR, fg=TEXT_COLOR_MEDIUM, anchor='w').grid(row=1, column=0, sticky="w", padx=(5, 0)) # Cost and Buy Button cost = self.calculate_upgrade_cost(key) cost_str = f"{cost:,}" # Formatted cost button_text = "خرید" button_color = BUTTON_COLOR button_hover_color = BUTTON_HOVER_COLOR # Check if enough balance if self.balance.get() < cost: button_text = "موجودی کافی نیست" button_color = '#cccccc' # Greyed out button_hover_color = '#cccccc' buy_button = tk.Button(frame, text=f"{button_text} ({cost_str})", font=FONT_SMALL, command=lambda k=key: self.buy_upgrade(k), bg=button_color, fg='white', activebackground=button_hover_color, activeforeground='white', relief=tk.FLAT, borderwidth=0, padx=10, pady=5) buy_button.grid(row=0, column=1, rowspan=2, sticky="e", padx=5) row_num += 1 # Configure grid weights for responsiveness self.scrollable_upgrade_frame.grid_columnconfigure(0, weight=1) # Upgrade info takes available space self.scrollable_upgrade_frame.grid_columnconfigure(1, weight=0) # Button takes minimum space # --- Core Game Logic (mostly unchanged, minor tweaks for UI) --- def load_settings(self): if os.path.exists(SETTINGS_FILE): try: with open(SETTINGS_FILE, 'r', encoding='utf-8') as f: data = json.load(f) loaded_upgrades = {} # Load upgrades ensuring all fields exist for key, initial_data in INITIAL_UPGRADES.items(): upgrade_data = data.get("upgrades", {}).get(key, initial_data.copy()) for field, default_value in initial_data.items(): if field not in upgrade_data: upgrade_data[field] = default_value loaded_upgrades[key] = upgrade_data # Ensure upgrades dictionary always contains keys from INITIAL_UPGRADES for key, initial_data in INITIAL_UPGRADES.items(): if key not in loaded_upgrades: loaded_upgrades[key] = initial_data.copy() else: # Ensure all fields are present in loaded upgrades for field, default_val in initial_data.items(): if field not in loaded_upgrades[key]: loaded_upgrades[key][field] = default_val self.balance.set(data.get("balance", 0)) self.hourly_profit.set(data.get("hourly_profit", 0)) self.tap_value.set(data.get("tap_value", 1)) self.active_special_card = data.get("active_special_card", None) if self.active_special_card: try: end_time_str = data.get("special_card_end_time") if end_time_str: self.special_card_end_time = datetime.datetime.fromisoformat(end_time_str) else: self.special_card_end_time = None except ValueError: self.active_special_card, self.special_card_end_time = None, None else: self.special_card_end_time = None self.last_hourly_profit_time = datetime.datetime.fromisoformat(data.get("last_hourly_profit_time", datetime.datetime.now().isoformat())) self.current_cost_multiplier.set(data.get("current_cost_multiplier", 1.0)) self.special_card_chance_boost.set(data.get("special_card_chance_boost", 0.0)) self.original_hourly_profit_for_boost = data.get("original_hourly_profit_for_boost", 0) # Load boost value too return loaded_upgrades except (json.JSONDecodeError, FileNotFoundError, ValueError, KeyError) as e: print(f"Error loading settings: {e}. Creating default settings.") return self.create_default_settings() else: return self.create_default_settings() def create_default_settings(self): default_upgrades = {} for key, value in INITIAL_UPGRADES.items(): default_upgrades[key] = value.copy() return default_upgrades def save_settings_on_exit(self): self.master.protocol("WM_DELETE_WINDOW", self.on_exit) def on_exit(self): self.save_settings() self.master.destroy() def save_settings(self): settings = { "balance": self.balance.get(), "hourly_profit": self.hourly_profit.get(), "tap_value": self.tap_value.get(), "upgrades": self.upgrades, "active_special_card": self.active_special_card, "special_card_end_time": self.special_card_end_time.isoformat() if self.special_card_end_time else None, "last_hourly_profit_time": self.last_hourly_profit_time.isoformat(), "current_cost_multiplier": self.current_cost_multiplier.get(), "special_card_chance_boost": self.special_card_chance_boost.get(), "original_hourly_profit_for_boost": self.original_hourly_profit_for_boost # Save boost value } try: with open(SETTINGS_FILE, 'w', encoding='utf-8') as f: json.dump(settings, f, indent=4, ensure_ascii=False) except IOError as e: print(f"Error saving settings: {e}") def recalculate_profits(self): base_tap = 1 base_hourly = 0 cost_reduction_percent = 0.0 # Recalculate based on current upgrade levels for key, upgrade_data in self.upgrades.items(): level = upgrade_data.get('level', 0) if level > 0: if key == "tap_boost": base_tap += upgrade_data.get("tap_increase", 0) * level elif key == "hourly_profit_boost": base_hourly += upgrade_data.get("hourly_profit", 0) * level elif key == "cost_reduction": cost_reduction_percent += upgrade_data.get("cost_reduction_percent", 0.0) * level elif key == "special_card_chance": self.special_card_chance_boost.set(upgrade_data.get("special_card_chance_boost", 0.0) * level) self.tap_value.set(base_tap) # Apply hourly boost multiplier ONLY IF the card is active and it's the x5 boost current_hourly_profit = base_hourly if self.active_special_card == "hourly_boost_x5": # Ensure original_hourly_profit_for_boost is set correctly before applying multiplier self.original_hourly_profit_for_boost = base_hourly # Store the base hourly profit current_hourly_profit = self.original_hourly_profit_for_boost * SPECIAL_CARDS["hourly_boost_x5"]["effect"](1) # Apply the multiplier else: self.original_hourly_profit_for_boost = 0 # Reset if not x5 boost card current_hourly_profit = base_hourly # Use the base hourly profit self.hourly_profit.set(current_hourly_profit) self.current_cost_multiplier.set(max(0.1, 1.0 - cost_reduction_percent)) def calculate_upgrade_cost(self, upgrade_key): upgrade_data = self.upgrades[upgrade_key] base_cost = upgrade_data["base_cost"] level = upgrade_data["level"] cost_multiplier = upgrade_data["cost_multiplier"] effective_cost_multiplier = self.current_cost_multiplier.get() # Calculate cost: base * (multiplier^level) * reduction_multiplier cost = base_cost * (cost_multiplier ** level) * effective_cost_multiplier return math.ceil(cost) # Use ceiling to ensure cost is always rounded up def increase_balance_by_tap(self): tap = self.tap_value.get() current_tap_value = tap # Apply special card effect if active if self.active_special_card == "double_tap": current_tap_value *= 2 self.balance.set(self.balance.get() + current_tap_value) self.update_display() # Optionally, consume the double tap card after one use if it's meant to be single-use per activation # self.deactivate_special_card() # Uncomment if double tap should only apply once per activation else: self.balance.set(self.balance.get() + current_tap_value) self.update_display() def buy_upgrade(self, upgrade_key): upgrade_data = self.upgrades[upgrade_key] cost = self.calculate_upgrade_cost(upgrade_key) is_free_upgrade_card = (self.active_special_card == "free_upgrade") if is_free_upgrade_card: # If free upgrade card is active, the cost is effectively zero for this purchase # But we still need to consume the card pass # Cost is ignored, card will be consumed later elif self.balance.get() < cost: print("Not enough balance!") # Show message to user return # Do not proceed if balance is insufficient and not a free card # If we reach here, either balance is sufficient OR it's a free upgrade card # Deduct cost only if it's not a free upgrade card purchase if not is_free_upgrade_card: self.balance.set(self.balance.get() - cost) # Increase level and update data upgrade_data["level"] += 1 self.upgrades[upgrade_key] = upgrade_data # Recalculate profits/tap value AFTER the upgrade level is updated self.recalculate_profits() # Consume the free upgrade card if it was used if is_free_upgrade_card: self.deactivate_special_card() self.update_display() self.load_upgrade_buttons() # Refresh the upgrade buttons to show new costs/levels def add_hourly_profit_periodically(self): now = datetime.datetime.now() time_elapsed = (now - self.last_hourly_profit_time).total_seconds() # Calculate profit based on current hourly_profit value # Ensure hourly_profit reflects any active multipliers (like x5 boost) profit_per_second = self.hourly_profit.get() / 3600.0 earned_profit = int(profit_per_second * time_elapsed) if earned_profit > 0: self.balance.set(self.balance.get() + earned_profit) self.last_hourly_profit_time = now # Reset timer only when profit is earned self.update_display() # Schedule next check self.master.after(60000, self.add_hourly_profit_periodically) # Check every minute def check_special_cards(self): if self.active_special_card and self.special_card_end_time: if datetime.datetime.now() >= self.special_card_end_time: self.deactivate_special_card() else: self.update_special_card_label() self.master.after(1000, self.check_special_cards) # Check every second def update_special_card_label(self): if self.active_special_card: card_info = SPECIAL_CARDS.get(self.active_special_card) if card_info and self.special_card_end_time: remaining_time = int((self.special_card_end_time - datetime.datetime.now()).total_seconds()) icon = card_info.get("icon", "") self.special_card_label.config(text=f"{icon} {card_info['name']} ({remaining_time}s)") else: # Card info missing or time ended but not caught? self.special_card_label.config(text="") self.active_special_card = None self.special_card_end_time = None else: self.special_card_label.config(text="") def deactivate_special_card(self): if self.active_special_card: card_info = SPECIAL_CARDS.get(self.active_special_card) print(f"Special card '{card_info['name']}' ended.") # Log message # Revert effects if necessary if self.active_special_card == "hourly_boost_x5": # Restore hourly profit to its base value before the boost self.hourly_profit.set(self.original_hourly_profit_for_boost) self.original_hourly_profit_for_boost = 0 # Clear stored value elif self.active_special_card == "double_tap": # Tap value is read dynamically, so no explicit revert needed here pass elif self.active_special_card == "free_upgrade": # No ongoing effect to revert pass self.active_special_card = None self.special_card_end_time = None self.update_special_card_label() self.update_display() # Update display to reflect changes if any def trigger_random_special_card(self): base_chance = 0.01 # 1% base chance total_chance = base_chance + self.special_card_chance_boost.get() if not self.active_special_card and random.random() < total_chance: card_key = random.choice(list(SPECIAL_CARDS.keys())) self.activate_special_card(card_key) self.master.after(5000, self.trigger_random_special_card) # Check every 5 seconds def activate_special_card(self, card_key): if card_key in SPECIAL_CARDS: card_info = SPECIAL_CARDS[card_key] duration = card_info["duration"] self.active_special_card = card_key self.special_card_end_time = datetime.datetime.now() + datetime.timedelta(seconds=duration) # Apply immediate effect if any if card_key == "hourly_boost_x5": self.original_hourly_profit_for_boost = self.hourly_profit.get() # Store current profit BEFORE applying boost self.hourly_profit.set(self.original_hourly_profit_for_boost * card_info['effect'](1)) # Apply the multiplier elif card_key == "free_upgrade": # Effect is applied during purchase, just mark it active pass elif card_key == "double_tap": # Effect applied during tap pass print(f"Special card activated: {card_info['name']} for {duration} seconds.") self.update_special_card_label() self.update_display() # Update display to reflect changes immediately (e.g., hourly profit) else: print(f"Special card with key '{card_key}' not found.") def update_display(self): # Update balance label (formatted) self.balance_label.config(text=f"{self.balance.get():,}") # Update profit label with current tap value and hourly profit tap_val = self.tap_value.get() hourly_prof = self.hourly_profit.get() profit_text = f"Tap: {tap_val:,} | Hourly: {hourly_prof:,}" # Add indicators for active special cards if self.active_special_card == "double_tap": profit_text += " (Tap x2)" elif self.active_special_card == "hourly_boost_x5": profit_text += f" (Hourly x{SPECIAL_CARDS['hourly_boost_x5']['effect'](1)})" self.profit_label.config(text=profit_text) # Update costs on upgrade buttons (this is called after purchase or when needed) self.load_upgrade_buttons() def auto_save(self): self.save_settings() self.master.after(300000, self.auto_save) # Save every 5 minutes # --- Main Execution --- if __name__ == "__main__": root = tk.Tk() game = HamsterCombatGame(root) root.mainloop()
خب کد را اجرا کنید ، صفحه پایین را می بینید.

اینم از این ، نسخه سادش هست و خودتون این را ارتقا بدهید .
برای دانلود همین پایتون یا فایل تبدیل شده به برنامه روی نوشته لینک بزنید و 15ثانیه صبر کنید و فایل را دریافت کنید .
اگر ایده یا پروژه ای دیگری میخواهید در نظر ها بنویسید .