import pygame import asyncio import math import random # ========================= # CONFIG & CONSTANTS # ========================= WIDTH, HEIGHT = 1000, 750 SUN_POS = (WIDTH // 2, HEIGHT // 2 + 30) SUN_RADIUS = 45 FPS = 60 COLOR_BG = (10, 10, 15) COLOR_TEXT = (255, 255, 255) COLOR_PROD = (0, 255, 255) COLOR_NEUTRAL = (80, 80, 80) # --- تعديل: خليت الكواكب المحايدة لونها رمادي باهت لتبين الألوان التانية --- DIFFICULTY_MAP = {"Easy": 250, "Medium": 180, "Hard": 100} PRODUCTION_MULTIPLIER = {"Easy": 1.3, "Medium": 1.0, "Hard": 0.7} # تأثير الصعوبة على الإنتاج # Quick send presets SEND_PRESETS = { pygame.K_1: 0.25, pygame.K_2: 0.50, pygame.K_3: 0.75, pygame.K_4: 1.00 } class Planet: def __init__(self, pid, owner, dist, angle, vel, color, production): self.id = pid self.owner = owner self.dist = dist self.angle = angle self.vel = vel * 0.3 self.base_color = color self.production = production self.radius = 15 + (production * 3) self.ships = 20 if owner != -1 else random.randint(15, 40) self.x, self.y = 0, 0 self.selected = False def update(self): self.x = SUN_POS[0] + math.cos(self.angle) * self.dist self.y = SUN_POS[1] + math.sin(self.angle) * self.dist self.angle += self.vel if self.owner != -1: self.ships += self.production / 120 # أسرع في الإنتاج def draw(self, screen, font_main, font_sub): if self.selected: pygame.draw.circle(screen, (255, 255, 255), (int(self.x), int(self.y)), self.radius + 4, 2) pygame.draw.circle(screen, self.base_color, (int(self.x), int(self.y)), self.radius) pygame.draw.circle(screen, (30, 30, 30), (int(self.x), int(self.y)), self.radius, 2) txt = font_main.render(str(int(self.ships)), True, COLOR_TEXT) txt_rect = txt.get_rect(center=(self.x, self.y)) screen.blit(txt, txt_rect) prod_txt = font_sub.render(f"+{self.production}", True, COLOR_PROD) screen.blit(prod_txt, (self.x - 8, self.y - self.radius - 15)) class Fleet: def __init__(self, owner, color, start_pos, target, count): self.owner = owner self.color = color self.x, self.y = start_pos self.target = target self.ships = count self.total_ships = count # العدد الإجمالي الذي سيتم إرساله # حساب السرعة بناءً على عدد السفن (لوغاريتمي مثل Orbit Wars) if count >= 1000: self.speed = 5.8 elif count >= 500: self.speed = 5.0 elif count >= 100: self.speed = 3.5 elif count >= 20: self.speed = 2.5 else: self.speed = 2.0 self.active = True self.trail = [] # آثار الحركة self.distance_traveled = 0 def update(self): dist_to_sun = math.hypot(SUN_POS[0] - self.x, SUN_POS[1] - self.y) if dist_to_sun < SUN_RADIUS: self.active = False return dx = self.target.x - self.x dy = self.target.y - self.y dist = math.hypot(dx, dy) if dist < self.target.radius * 1.5: self.impact() self.active = False else: angle = math.atan2(dy, dx) self.x += math.cos(angle) * self.speed self.y += math.sin(angle) * self.speed self.distance_traveled += self.speed # حفظ آثار الحركة if len(self.trail) < 30: self.trail.append((self.x, self.y)) else: self.trail.pop(0) self.trail.append((self.x, self.y)) def impact(self): if self.target.owner == self.owner: self.target.ships += self.ships else: # قتال: الأكبر ينجي والباقي ينتقل self.target.ships -= self.ships if self.target.ships <= 0: self.target.owner = self.owner self.target.ships = abs(self.target.ships) self.target.base_color = self.color def draw(self, screen): # رسم الآثار بتدرج for i, (tx, ty) in enumerate(self.trail): size = max(1, int(3 - (i / max(len(self.trail), 1)) * 2)) pygame.draw.circle(screen, self.color, (int(tx), int(ty)), size, 1) # حساب اتجاه السفينة والحجم angle = math.atan2(self.target.y - self.y, self.target.x - self.x) ship_size = max(3, min(8, self.ships / 80)) # حساب نقاط المثلث البسيط # نقطة الرأس (الأمام) tip_x = self.x + math.cos(angle) * ship_size * 2.5 tip_y = self.y + math.sin(angle) * ship_size * 2.5 # نقطتا القاعدة (الخلف) base_left_x = self.x + math.cos(angle + 2.5) * ship_size base_left_y = self.y + math.sin(angle + 2.5) * ship_size base_right_x = self.x + math.cos(angle - 2.5) * ship_size base_right_y = self.y + math.sin(angle - 2.5) * ship_size # رسم المثلث البسيط points = [ (int(tip_x), int(tip_y)), (int(base_left_x), int(base_left_y)), (int(base_right_x), int(base_right_y)) ] pygame.draw.polygon(screen, self.color, points) pygame.draw.polygon(screen, (255, 255, 255), points, 1) class OnyxWarsPro: def __init__(self): pygame.init() self.screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("onyx_wars - Galaxy Wars") self.font_l = pygame.font.SysFont("Arial", 24, bold=True) self.font_m = pygame.font.SysFont("Arial", 16, bold=True) self.font_s = pygame.font.SysFont("Arial", 12, bold=True) self.state = "MENU" self.num_enemies = 1 self.player_color = (0, 162, 255) self.difficulty = "Medium" self.menu_options = ["Enemies", "Color", "Difficulty", "Start"] self.menu_index = 0 self.colors_list = [(0, 162, 255), (50, 255, 50), (255, 50, 50)] self.color_idx = 0 self.diffs_list = ["Easy", "Medium", "Hard"] self.diff_idx = 1 self.planets = [] self.fleets = [] self.dragging = False self.drag_start_p = None self.selected_planet = None self.target_planet = None self.ai_turn_counter = 0 self.ai_turn_interval = 15 # AI يلعب كل 15 frame def check_victory(self): """Check win/loss conditions""" enemy_planets = sum(1 for p in self.planets if p.owner > 0) enemy_ships = sum(p.ships for p in self.planets if p.owner > 0) + sum(f.ships for f in self.fleets if f.owner > 0) if enemy_planets == 0 and enemy_ships == 0: return "WIN" # لاعب يفوز player_planets = sum(1 for p in self.planets if p.owner == 0) player_ships = sum(p.ships for p in self.planets if p.owner == 0) + sum(f.ships for f in self.fleets if f.owner == 0) if player_planets == 0 and player_ships == 0: return "LOSS" # لاعب يخسر return None def draw_win_screen(self): """عرض شاشة الفوز""" self.screen.fill(COLOR_BG) title = self.font_l.render("🎉 YOU WIN! 🎉", True, (0, 255, 100)) self.screen.blit(title, (WIDTH//2 - 150, 250)) restart_txt = self.font_m.render("Press SPACE to return to menu", True, COLOR_TEXT) self.screen.blit(restart_txt, (WIDTH//2 - 180, 350)) def draw_loss_screen(self): """عرض شاشة الخسارة""" self.screen.fill(COLOR_BG) title = self.font_l.render("GAME OVER", True, (255, 50, 50)) self.screen.blit(title, (WIDTH//2 - 120, 250)) restart_txt = self.font_m.render("Press SPACE to return to menu", True, COLOR_TEXT) self.screen.blit(restart_txt, (WIDTH//2 - 180, 350)) def draw_menu(self): self.screen.fill(COLOR_BG) title = self.font_l.render("RUI GALAXY WARS", True, (0, 255, 150)) self.screen.blit(title, (WIDTH//2 - 120, 100)) for i, option in enumerate(self.menu_options): color = (0, 255, 150) if i == self.menu_index else COLOR_TEXT if option == "Enemies": text = f"Enemies: {self.num_enemies} (Left/Right)" elif option == "Color": text = f"Color: {self.player_color} (Left/Right)" elif option == "Difficulty": text = f"Difficulty: {self.difficulty} (Left/Right)" else: text = "--- PRESS SPACE TO START ---" surf = self.font_m.render(text, True, color) self.screen.blit(surf, (WIDTH//2 - 150, 250 + i*50)) def draw_top_bar(self): pygame.draw.rect(self.screen, (15, 20, 35), (0, 0, WIDTH, 60)) pygame.draw.line(self.screen, (50, 50, 80), (0, 60), (WIDTH, 60), 2) p_ships = sum(p.ships for p in self.planets if p.owner == 0) + sum(f.ships for f in self.fleets if f.owner == 0) p_planets = sum(1 for p in self.planets if p.owner == 0) txt_p = self.font_m.render(f"RUI Company: {int(p_ships)} ships | {p_planets} planets", True, self.player_color) self.screen.blit(txt_p, (20, 15)) for i in range(self.num_enemies): e_ships = sum(p.ships for p in self.planets if p.owner == i+1) + sum(f.ships for f in self.fleets if f.owner == i+1) e_planets = sum(1 for p in self.planets if p.owner == i+1) e_color = self.planets[1+i].base_color if len(self.planets) > 1+i else (255,0,0) txt_e = self.font_s.render(f"Enemy {i+1}: {int(e_ships)}sh|{e_planets}pl", True, e_color) self.screen.blit(txt_e, (WIDTH - 280 - (i*180), 20)) def draw_game_help(self): """عرض تعليمات اللعب والمعلومات الحالية""" # الأساسيات txt1 = self.font_s.render("1. CLICK your planet → 2. CLICK target → 3. PRESS 1-4 for amount", True, (150, 200, 255)) self.screen.blit(txt1, (20, HEIGHT - 40)) txt_esc = self.font_s.render("Press ESC to deselect", True, (200, 100, 100)) self.screen.blit(txt_esc, (20, HEIGHT - 20)) if self.selected_planet: txt2 = self.font_s.render(f"SELECTED: Planet #{self.selected_planet.id} ({int(self.selected_planet.ships):.0f} ships, +{self.selected_planet.production}/turn)", True, (100, 255, 100)) self.screen.blit(txt2, (WIDTH - 500, HEIGHT - 40)) def draw_attack_lines(self): """رسم خطوط الهجوم من الكوكب المختار - معطل""" # لا يتم رسم المسارات pass def setup_game(self): self.planets = [] self.fleets = [] self.planets.append(Planet(0, 0, 160, 0, 0.005, self.player_color, 5)) enemy_colors = [(255, 50, 50), (200, 50, 255), (50, 255, 50)] for i in range(self.num_enemies): angle = (2 * math.pi / (self.num_enemies + 1)) * (i + 1) self.planets.append(Planet(i+1, i+1, 280, angle, -0.004, enemy_colors[i], 4)) for i in range(len(self.planets), 12): d = random.randint(150, 380) p = random.randint(1, 4) self.planets.append(Planet(i, -1, d, random.random()*6, random.uniform(0.002, 0.005), COLOR_NEUTRAL, p)) self.ai_turn_interval = max(8, 20 - (5 if self.difficulty == "Hard" else 0)) # AI أسرع في الصعوبة العالية self.state = "GAME" def calculate_target_priority(self, from_planet): """حساب أولوية الأهداف بناءً على استراتيجية متقدمة""" targets = [(t, 0) for t in self.planets if t != from_planet] priorities = [] for target, _ in targets: dist = math.hypot(target.x - from_planet.x, target.y - from_planet.y) strength_diff = from_planet.ships - target.ships priority = 0 if target.owner == 0: # عدو (اللاعب) - أولوية عالية جداً priority = 100 - (dist / 5) if strength_diff > 30: priority += 50 elif target.owner == -1: # محايد - أولوية متوسطة if target.production > 3: priority = 70 - (dist / 8) + (target.production * 10) else: priority = 40 - (dist / 10) if strength_diff > target.ships * 0.5: priority += 30 elif target.owner != from_planet.owner: # عدو آخر if strength_diff > target.ships * 0.3: priority = 60 - (dist / 6) else: priority = 20 - (dist / 15) else: # نفس المالك - تعزيز priority = -100 priorities.append((target, priority)) return sorted(priorities, key=lambda x: x[1], reverse=True) def enemy_ai_turn(self): """AI محسّن يلعب بذكاء""" for p in self.planets: if p.owner <= 0: continue # تقييم قوة العدو والتحالفات enemy_strength = sum(x.ships for x in self.planets if x.owner == 0) + \ sum(f.ships for f in self.fleets if f.owner == 0) own_strength = sum(x.ships for x in self.planets if x.owner == p.owner) + \ sum(f.ships for f in self.fleets if f.owner == p.owner) # احسب الحد الأدنى للهجوم بناءً على الصعوبة min_ships = DIFFICULTY_MAP.get(self.difficulty, 180) / 100 # إذا كان لديك سفن كافية if p.ships > min_ships: targets = self.calculate_target_priority(p) if targets and len(targets) > 0: target, priority = targets[0] if priority > 0: # هناك هدف يستحق # تحديد نسبة الإرسال بناءً على الموقف send_ratio = 0.25 if target.owner == 0: # اللاعب - أولوية عالية if own_strength > enemy_strength * 1.5: send_ratio = 0.7 elif own_strength > enemy_strength: send_ratio = 0.55 else: send_ratio = 0.35 elif target.owner == -1: # محايد send_ratio = min(0.5, (p.ships / max(target.ships + 5, 1)) * 0.4) elif target.owner != p.owner: # عدو آخر if own_strength > enemy_strength: send_ratio = 0.45 else: send_ratio = 0.28 send_count = int(p.ships * send_ratio) if send_count > 5: # يجب أن يكون هناك حد أدنى p.ships -= send_count self.fleets.append(Fleet(p.owner, p.base_color, (p.x, p.y), target, send_count)) async def run(self): clock = pygame.time.Clock() while True: if self.state == "MENU": self.draw_menu() for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: self.menu_index = max(0, self.menu_index - 1) elif event.key == pygame.K_DOWN: self.menu_index = min(len(self.menu_options)-1, self.menu_index + 1) elif event.key == pygame.K_RIGHT: if self.menu_index == 0: self.num_enemies = min(3, self.num_enemies + 1) elif self.menu_index == 1: self.color_idx = (self.color_idx + 1) % len(self.colors_list) self.player_color = self.colors_list[self.color_idx] elif self.menu_index == 2: self.diff_idx = (self.diff_idx + 1) % len(self.diffs_list) self.difficulty = self.diffs_list[self.diff_idx] elif event.key == pygame.K_LEFT: if self.menu_index == 0: self.num_enemies = max(1, self.num_enemies - 1) elif self.menu_index == 1: self.color_idx = (self.color_idx - 1) % len(self.colors_list) self.player_color = self.colors_list[self.color_idx] elif self.menu_index == 2: self.diff_idx = (self.diff_idx - 1) % len(self.diffs_list) self.difficulty = self.diffs_list[self.diff_idx] elif event.key == pygame.K_SPACE: self.setup_game() elif self.state == "GAME": self.screen.fill(COLOR_BG) pygame.draw.circle(self.screen, (255, 180, 0), SUN_POS, SUN_RADIUS) pygame.draw.circle(self.screen, (255, 220, 100), SUN_POS, SUN_RADIUS - 10) self.draw_top_bar() for event in pygame.event.get(): if event.type == pygame.QUIT: return pos = pygame.mouse.get_pos() if event.type == pygame.MOUSEBUTTONDOWN: clicked = next((p for p in self.planets if math.hypot(pos[0]-p.x, pos[1]-p.y) < p.radius), None) if clicked and clicked.owner == 0: if self.selected_planet == clicked: # إلغاء التحديد self.selected_planet = None else: # تحديد كوكب جديد self.selected_planet = clicked # نظام الإرسال السريع: اختر كوكب -> اختر هدف -> اضغط 1-4 if event.type == pygame.MOUSEBUTTONDOWN and self.selected_planet: target = next((p for p in self.planets if math.hypot(pos[0]-p.x, pos[1]-p.y) < p.radius), None) if target and target != self.selected_planet: # اسأل عن كم سفينة سيتم إرسالها # سيتم تحديده في الحدث التالي (KEYDOWN) self.target_planet = target # اختصارات لوحة المفاتيح للإرسال السريع if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.selected_planet = None self.target_planet = None elif self.selected_planet and hasattr(self, 'target_planet') and self.target_planet: if event.key in SEND_PRESETS: percent = SEND_PRESETS[event.key] amt = int(self.selected_planet.ships * percent) if amt > 0: self.selected_planet.ships -= amt self.fleets.append(Fleet(0, self.player_color, (self.selected_planet.x, self.selected_planet.y), self.target_planet, amt)) self.enemy_ai_turn() self.selected_planet = None self.target_planet = None for p in self.planets: p.update() p.draw(self.screen, self.font_m, self.font_s) for f in self.fleets[:]: f.update() f.draw(self.screen) if not f.active: self.fleets.remove(f) # رسم خطوط الهجوم عند اختيار كوكب self.draw_attack_lines() # رسم الكوكب المختار وتفاصيل الإرسال if self.selected_planet: pygame.draw.circle(self.screen, (100, 255, 100), (int(self.selected_planet.x), int(self.selected_planet.y)), self.selected_planet.radius + 8, 4) txt = self.font_m.render(f"SELECTED: {int(self.selected_planet.ships)} ships", True, (100, 255, 100)) self.screen.blit(txt, (self.selected_planet.x - 80, self.selected_planet.y - self.selected_planet.radius - 35)) if hasattr(self, 'target_planet') and self.target_planet: # عرض تفاصيل الإرسال txt2 = self.font_s.render("PRESS 1, 2, 3, or 4", True, (150, 200, 255)) self.screen.blit(txt2, (self.selected_planet.x - 60, self.selected_planet.y - self.selected_planet.radius - 55)) txt3 = self.font_s.render("(25%, 50%, 75%, 100%)", True, (100, 200, 255)) self.screen.blit(txt3, (self.selected_planet.x - 60, self.selected_planet.y - self.selected_planet.radius - 70)) # عرض الأرقام الفعلية for key, ratio in SEND_PRESETS.items(): ships_to_send = int(self.selected_planet.ships * ratio) if key == pygame.K_1: txt_prev = self.font_s.render(f"1: {ships_to_send} ships", True, (255, 200, 100)) self.screen.blit(txt_prev, (self.target_planet.x - 50, self.target_planet.y - 50)) elif key == pygame.K_2: txt_prev = self.font_s.render(f"2: {ships_to_send} ships", True, (255, 200, 100)) self.screen.blit(txt_prev, (self.target_planet.x - 50, self.target_planet.y - 30)) elif key == pygame.K_3: txt_prev = self.font_s.render(f"3: {ships_to_send} ships", True, (255, 200, 100)) self.screen.blit(txt_prev, (self.target_planet.x - 50, self.target_planet.y - 10)) elif key == pygame.K_4: txt_prev = self.font_s.render(f"4: {ships_to_send} ships", True, (255, 200, 100)) self.screen.blit(txt_prev, (self.target_planet.x - 50, self.target_planet.y + 10)) self.draw_game_help() # AI يلعب تلقائياً كل فترة self.ai_turn_counter += 1 if self.ai_turn_counter >= self.ai_turn_interval: self.enemy_ai_turn() self.ai_turn_counter = 0 # تحقق من الفوز/الخسارة result = self.check_victory() if result: self.state = result elif self.state == "WIN": self.draw_win_screen() for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: self.state = "MENU" self.menu_index = 0 elif self.state == "LOSS": self.draw_loss_screen() for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: self.state = "MENU" self.menu_index = 0 pygame.display.flip() await asyncio.sleep(0) clock.tick(FPS) if __name__ == "__main__": asyncio.run(OnyxWarsPro().run())