game.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import pygame
  2. import random
  3. # --- Константы ---
  4. WIDTH, HEIGHT = 1000, 750
  5. WHITE = (240, 240, 240)
  6. BLACK = (20, 20, 20)
  7. PANEL_COLOR = (44, 62, 80)
  8. ACCENT = (52, 152, 219)
  9. DISABLED = (127, 140, 141)
  10. DANGER = (231, 76, 60)
  11. SUCCESS = (46, 204, 113)
  12. GOLD = (241, 196, 15)
  13. PURPLE = (155, 89, 182)
  14. class FloatingText:
  15. def __init__(self, text, x, y, color):
  16. self.text = text
  17. self.x = x
  18. self.y = y
  19. self.color = color
  20. self.alpha = 255
  21. self.life = 60
  22. def update(self):
  23. self.y -= 1
  24. self.alpha -= 4
  25. self.life -= 1
  26. def draw(self, screen, font):
  27. if self.life > 0:
  28. surf = font.render(self.text, True, self.color)
  29. surf.set_alpha(max(0, self.alpha))
  30. screen.blit(surf, (self.x, self.y))
  31. class UltimateAdminGame:
  32. def __init__(self):
  33. pygame.init()
  34. self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
  35. pygame.display.set_caption("Администратор: Высшая Лига 2.0")
  36. self.clock = pygame.time.Clock()
  37. # Шрифты
  38. self.font_main = pygame.font.SysFont('Segoe UI', 19)
  39. self.font_bold = pygame.font.SysFont('Segoe UI', 24, bold=True)
  40. self.font_title = pygame.font.SysFont('Segoe UI', 32, bold=True)
  41. # Состояние игры
  42. self.reset_game()
  43. def reset_game(self):
  44. """Полный сброс всех параметров (для кнопки R)"""
  45. self.day = 1
  46. self.hour = 9
  47. self.week = 1
  48. self.stats = {"Репутация": 70, "Бюджет": 200, "Стресс": 0}
  49. self.display_stats = {k: float(v) for k, v in self.stats.items()}
  50. # Новинка: Система навыков (случайный бонус при старте)
  51. self.perk = random.choice(["Экономный", "Стрессоустойчивый", "Любимчик"])
  52. if self.perk == "Экономный": self.stats["Бюджет"] += 50
  53. if self.perk == "Любимчик": self.stats["Репутация"] += 30
  54. self.logs = [f"Старт: Ваша особенность — '{self.perk}'", "Понедельник. Пора разгребать завалы."]
  55. self.floating_texts = []
  56. self.current_event = None
  57. self.game_over = False
  58. self.victory = False
  59. # Расширенный пул событий
  60. self.events_pool = [
  61. {"title": "Кофемашина взорвалась", "desc": ["Весь пол в липком латте.", "Сотрудники в панике без кофеина."], "options": [{"text": "Вызвать мастера (-25 Бюджет, -1ч)", "cost": 25, "mod": (5, -25, -5), "time": 1}, {"text": "Купить растворимый кофе (-5 Бюджет, -1ч)", "cost": 5, "mod": (-10, -5, 5), "time": 1}, {"text": "Заставить всех работать так (-2ч)", "cost": 0, "mod": (-15, 0, 20), "time": 2}]},
  62. {"title": "Вирусная атака", "desc": ["Бухгалтерия открыла письмо 'Ваш выигрыш'.", "Шифровальщик заблокировал сеть!"], "options": [{"text": "Заплатить хакерам (-60 Бюджет, -1ч)", "cost": 60, "mod": (0, -60, 15), "time": 1}, {"text": "Откатить систему (-4ч)", "cost": 0, "mod": (25, 0, 35), "time": 4}, {"text": "Изолировать сервер (-2ч)", "cost": 0, "mod": (-10, 0, 20), "time": 2}]},
  63. {"title": "Визит инвестора", "desc": ["Важный гость приехал без предупреждения.", "Нужно произвести впечатление."], "options": [{"text": "Устроить фуршет (-40 Бюджет, -2ч)", "cost": 40, "mod": (35, -40, 10), "time": 2}, {"text": "Провести презентацию (-3ч)", "cost": 0, "mod": (20, 0, 45), "time": 3}, {"text": "Делегировать помощнику (-1ч)", "cost": 0, "mod": (5, 0, -5), "time": 1}]},
  64. {"title": "Налоговая проверка", "desc": ["Инспектор требует документы за прошлый год.", "Кажется, мы что-то потеряли."], "options": [{"text": "Договориться на месте (-50 Бюджет)", "cost": 50, "mod": (-10, -50, 15), "time": 1}, {"text": "Искать архивы всю ночь (+40 Стресс)", "cost": 0, "mod": (30, 0, 40), "time": 4}, {"text": "Свалить на бухгалтера (-20 Репутация)", "cost": 0, "mod": (-20, 0, 10), "time": 2}]},
  65. {"title": "Корпоратив", "desc": ["Пятница! Команда хочет расслабиться.", "От этого зависит климат в офисе."], "options": [{"text": "Заказать пиццу (-15 Бюджет)", "cost": 15, "mod": (10, -15, -10), "time": 1}, {"text": "Снять караоке-бар (-45 Бюджет)", "cost": 45, "mod": (35, -45, -30), "time": 3}, {"text": "Работать сверхурочно (+30 Стресс)", "cost": 0, "mod": (-20, 10, 30), "time": 2}]},
  66. {"title": "Протечка крыши", "desc": ["Вода капает прямо на серверную стойку!", "Срочно нужны тазы или ремонт."], "options": [{"text": "Вызвать кровельщиков (-35 Бюджет)", "cost": 35, "mod": (10, -35, 5), "time": 1}, {"text": "Героически спасать железо (-4ч)", "cost": 0, "mod": (20, 0, 45), "time": 4}, {"text": "Ничего не делать (Риск!)", "cost": 0, "mod": (-40, -50, 20), "time": 2}]}
  67. ]
  68. self.pick_event()
  69. def pick_event(self):
  70. if not self.game_over and not self.victory:
  71. self.current_event = random.choice(self.events_pool)
  72. def create_floating(self, mod):
  73. r, b, s = mod
  74. pos_y = [180, 260, 340]
  75. changes = [r, b, s]
  76. for i, val in enumerate(changes):
  77. if val != 0:
  78. color = SUCCESS if val > 0 else DANGER
  79. if i == 2: color = DANGER if val > 0 else SUCCESS # Для стресса наоборот
  80. sign = "+" if val > 0 else ""
  81. self.floating_texts.append(FloatingText(f"{sign}{val}", 220, pos_y[i], color))
  82. def handle_choice(self, option):
  83. if self.stats["Бюджет"] >= option["cost"]:
  84. # Применение перков
  85. s_mod = option["mod"][2]
  86. if self.perk == "Стрессоустойчивый" and s_mod > 0: s_mod = int(s_mod * 0.7)
  87. self.create_floating((option["mod"][0], option["mod"][1], s_mod))
  88. self.stats["Репутация"] += option["mod"][0]
  89. self.stats["Бюджет"] += option["mod"][1]
  90. self.stats["Стресс"] += s_mod
  91. self.hour += option["time"]
  92. self.logs.append(f"{self.hour-option['time']}:00 - {option['text'].split(' (')[0]}")
  93. if self.hour >= 18:
  94. self.day += 1
  95. self.hour = 9
  96. self.stats["Стресс"] = max(0, self.stats["Стресс"] - 30)
  97. self.logs.append(f"--- День {self.day}. Ночной отдых -30 Стресс ---")
  98. if self.day > 5: # Конец рабочей недели
  99. self.day = 1
  100. self.week += 1
  101. self.stats["Бюджет"] += 150
  102. self.logs.append(f"*** Неделя {self.week}! Получен бюджет +150 ***")
  103. if self.week > 4: self.victory = True
  104. self.pick_event()
  105. self.check_game_over()
  106. def check_game_over(self):
  107. if self.stats["Репутация"] <= 0 or self.stats["Бюджет"] <= 0 or self.stats["Стресс"] >= 180:
  108. self.game_over = True
  109. def update_animations(self):
  110. for key in self.stats:
  111. diff = self.stats[key] - self.display_stats[key]
  112. self.display_stats[key] += diff * 0.1
  113. for ft in self.floating_texts[:]:
  114. ft.update()
  115. if ft.life <= 0: self.floating_texts.remove(ft)
  116. def draw_ui(self):
  117. self.screen.fill(WHITE)
  118. # Боковая панель
  119. pygame.draw.rect(self.screen, PANEL_COLOR, (0, 0, 260, HEIGHT))
  120. self.draw_text(f"НЕДЕЛЯ {self.week}", 130, 45, GOLD, True, self.font_bold)
  121. self.draw_text(f"ДЕНЬ {self.day} | {self.hour}:00", 130, 90, WHITE, True, self.font_main)
  122. self.draw_text(f"Перк: {self.perk}", 130, 130, PURPLE, True, self.font_main)
  123. y = 200
  124. for key in ["Репутация", "Бюджет", "Стресс"]:
  125. val = self.display_stats[key]
  126. real_val = self.stats[key]
  127. color = SUCCESS if (key != "Стресс" and real_val > 40) or (key == "Стресс" and real_val < 100) else DANGER
  128. self.draw_text(f"{key}: {int(real_val)}", 35, y, WHITE, False, self.font_main)
  129. pygame.draw.rect(self.screen, (60, 80, 100), (35, y + 30, 190, 10), border_radius=5)
  130. pygame.draw.rect(self.screen, color, (35, y + 30, max(0, min(val, 190)), 10), border_radius=5)
  131. y += 80
  132. for ft in self.floating_texts: ft.draw(self.screen, self.font_bold)
  133. # Логи
  134. pygame.draw.rect(self.screen, (230, 230, 230), (280, 560, 700, 170), border_radius=15)
  135. for i, log in enumerate(self.logs[-5:]):
  136. self.draw_text(log, 300, 575 + (i*30), (100, 100, 100) if i < 4 else BLACK)
  137. # Событие
  138. if not self.game_over and not self.victory:
  139. pygame.draw.rect(self.screen, (255, 255, 255), (280, 20, 700, 520), border_radius=15)
  140. self.draw_text(self.current_event["title"], 630, 70, PANEL_COLOR, True, self.font_title)
  141. for i, line in enumerate(self.current_event["desc"]):
  142. self.draw_text(line, 630, 140 + (i*30), (80, 80, 80), True)
  143. for i, opt in enumerate(self.current_event["options"]):
  144. self.button(opt, 300 + (i*80))
  145. elif self.game_over: self.overlay("ВЫ УВОЛЕНЫ", DANGER)
  146. elif self.victory: self.overlay("ВЫ - ГЕНИЙ УПРАВЛЕНИЯ", SUCCESS)
  147. def overlay(self, txt, color):
  148. pygame.draw.rect(self.screen, WHITE, (350, 250, 550, 250), border_radius=20)
  149. self.draw_text(txt, 625, 330, color, True, self.font_title)
  150. self.draw_text("R - Начать заново | ESC - Выход", 625, 400, BLACK, True, self.font_main)
  151. def draw_text(self, text, x, y, color=BLACK, center=False, font=None):
  152. f = font if font else self.font_main
  153. surf = f.render(str(text), True, color)
  154. rect = surf.get_rect(center=(x, y) if center else (x, y))
  155. if not center: rect.topleft = (x, y)
  156. self.screen.blit(surf, rect)
  157. def button(self, option, y):
  158. mouse = pygame.mouse.get_pos()
  159. click = pygame.mouse.get_pressed()
  160. rect = pygame.Rect(355, y, 550, 65)
  161. afford = self.stats["Бюджет"] >= option["cost"]
  162. hover = rect.collidepoint(mouse) and afford
  163. color = ACCENT if hover else (DISABLED if not afford else (100, 110, 120))
  164. pygame.draw.rect(self.screen, color, rect, border_radius=12)
  165. self.draw_text(option["text"], rect.centerx, rect.centery, WHITE, True, self.font_bold)
  166. if hover and click[0]:
  167. pygame.time.delay(200)
  168. self.handle_choice(option)
  169. def run(self):
  170. running = True
  171. while running:
  172. for event in pygame.event.get():
  173. if event.type == pygame.QUIT: running = False
  174. if event.type == pygame.KEYDOWN:
  175. if event.key == pygame.K_ESCAPE: running = False
  176. if event.key == pygame.K_r: self.reset_game()
  177. self.update_animations()
  178. self.draw_ui()
  179. pygame.display.flip()
  180. self.clock.tick(60)
  181. pygame.quit()
  182. if __name__ == "__main__":
  183. UltimateAdminGame().run()