Advertisement
Chl_Snt

GhostBusters

Apr 12th, 2025
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.41 KB | None | 0 0
  1. import tkinter as tk
  2. import math
  3. import random
  4. import colorsys
  5.  
  6. BALL_COUNT = 1000
  7. SPEED_RANGE = (1, 4)
  8. RADIUS_RANGE = (5, 15)
  9.  
  10. root = tk.Tk()
  11. root.title("Мячики")
  12. root.geometry("800x600")
  13. root.resizable(False, False)
  14.  
  15. canvas = tk.Canvas(root, bg="white", width=800, height=600)
  16. canvas.pack()
  17.  
  18. target_x, target_y = 400, 300
  19. storage = []
  20. balls = []
  21.  
  22. is_sucking = False
  23. is_blowing = False
  24. is_repelling = False
  25.  
  26. canvas.bind("<Motion>", lambda e: update_target(e))
  27.  
  28. canvas.bind("<ButtonPress-1>", lambda e: set_flag("blow", True))
  29. canvas.bind("<ButtonRelease-1>", lambda e: set_flag("blow", False))
  30. canvas.bind("<ButtonPress-2>", lambda e: set_flag("repel", True))
  31. canvas.bind("<ButtonRelease-2>", lambda e: set_flag("repel", False))
  32. canvas.bind("<ButtonPress-3>", lambda e: set_flag("suck", True))
  33. canvas.bind("<ButtonRelease-3>", lambda e: set_flag("suck", False))
  34.  
  35. def set_flag(action, value):
  36. global is_sucking, is_blowing, is_repelling
  37. if action == "suck":
  38. is_sucking = value
  39. elif action == "blow":
  40. is_blowing = value
  41. elif action == "repel":
  42. is_repelling = value
  43.  
  44. def pastel_color():
  45. h = random.random()
  46. s = 0.4
  47. v = 0.95
  48. r, g, b = colorsys.hsv_to_rgb(h, s, v)
  49. return f"#{int(r*255):02x}{int(g*255):02x}{int(b*255):02x}"
  50.  
  51. def update_target(event):
  52. global target_x, target_y
  53. target_x = event.x
  54. target_y = event.y
  55.  
  56. def update_storage_text():
  57. canvas.itemconfig(storage_text, text=f"Storage: {len(storage)}")
  58.  
  59. def suck_nearby(cx, cy):
  60. global storage
  61. for ball in balls[:]:
  62. dx = ball["x"] - cx
  63. dy = ball["y"] - cy
  64. dist = math.hypot(dx, dy)
  65. if dist < 20 and len(storage) < BALL_COUNT:
  66. canvas.delete(ball["id"])
  67. balls.remove(ball)
  68. storage.append(ball)
  69. update_storage_text()
  70.  
  71. def blow_from_storage(cx, cy):
  72. global storage
  73. for _ in range(min(len(storage), 5)):
  74. ball = storage.pop()
  75. r = ball["r"]
  76. x = cx + random.randint(-30, 30)
  77. y = cy + random.randint(-30, 30)
  78. color = pastel_color()
  79. ball_id = canvas.create_oval(x - r, y - r, x + r, y + r, fill=color, outline="")
  80. ball.update({
  81. "x": x,
  82. "y": y,
  83. "vx": random.uniform(-3, 3),
  84. "vy": random.uniform(-3, 3),
  85. "id": ball_id,
  86. "color": color,
  87. "repel_timer": 20,
  88. })
  89. balls.append(ball)
  90. update_storage_text()
  91.  
  92. def repel_balls(cx, cy):
  93. for ball in balls:
  94. dx = ball["x"] - cx
  95. dy = ball["y"] - cy
  96. dist = math.hypot(dx, dy) + 0.01
  97. if dist < 200:
  98. force = 12 / dist
  99. ball["vx"] += force * dx
  100. ball["vy"] += force * dy
  101. ball["repel_timer"] = 20
  102.  
  103. for _ in range(BALL_COUNT):
  104. r = random.randint(*RADIUS_RANGE)
  105. x = random.randint(r, 800 - r)
  106. y = random.randint(r, 600 - r)
  107. color = pastel_color()
  108. speed = random.uniform(*SPEED_RANGE)
  109. ball_id = canvas.create_oval(x - r, y - r, x + r, y + r, fill=color, outline="")
  110. balls.append({
  111. "x": x,
  112. "y": y,
  113. "vx": 0,
  114. "vy": 0,
  115. "r": r,
  116. "speed": speed,
  117. "id": ball_id,
  118. "color": color,
  119. "repel_timer": 0,
  120. })
  121.  
  122. storage_text = canvas.create_text(790, 20, text="Storage: 0", anchor="ne", font=("Arial", 12), fill="black")
  123.  
  124. def move_balls():
  125. if is_sucking:
  126. suck_nearby(target_x, target_y)
  127. if is_blowing:
  128. blow_from_storage(target_x, target_y)
  129. if is_repelling:
  130. repel_balls(target_x, target_y)
  131.  
  132. for ball in balls:
  133. if ball["repel_timer"] > 0:
  134. ball["x"] += ball["vx"]
  135. ball["y"] += ball["vy"]
  136. ball["vx"] *= 0.9
  137. ball["vy"] *= 0.9
  138. ball["repel_timer"] -= 1
  139. else:
  140. dx = target_x - ball["x"]
  141. dy = target_y - ball["y"]
  142. dist = math.hypot(dx, dy)
  143. if dist > 1:
  144. step_x = ball["speed"] * dx / dist
  145. step_y = ball["speed"] * dy / dist
  146. ball["x"] += step_x
  147. ball["y"] += step_y
  148.  
  149. r = ball["r"]
  150. canvas.coords(ball["id"],
  151. ball["x"] - r, ball["y"] - r,
  152. ball["x"] + r, ball["y"] + r)
  153. root.after(16, move_balls)
  154.  
  155. move_balls()
  156. root.mainloop()
  157.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement