Advertisement
here2share

# tk_gravity_repel.py

Apr 12th, 2023
840
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.12 KB | None | 0 0
  1. # tk_gravity_repel.py
  2.  
  3. from tkinter import *
  4. import math
  5. import random
  6.  
  7. # Define constants
  8. NUM_POINTS = 50
  9. RADIUS = 5
  10. WIDTH = 500
  11. HEIGHT = 500
  12. GRAVITY_CONSTANT = 100 # Define the repelling gravity constant, enough to keep every circle from ever colliding
  13. MAX_SPEED = 4 # Define the maximum velocity change allowed
  14. DELAY = 50 # Define the delay between updates
  15. MIN_DISTANCE = 25 # Minimum distance between two circles
  16. STEER = 80
  17.  
  18. # Initialize tkinter window
  19. root = Tk()
  20. root.title("Gravity Repel")
  21. canvas = Canvas(root, width=WIDTH, height=HEIGHT)
  22. canvas.pack()
  23.  
  24. # Define function for calculating distance between two points
  25. def distance(x1, y1, x2, y2):
  26.     return math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
  27.  
  28. # Define function for calculating the repelling force between nearest two points
  29. def repel_force(x1, y1, x2, y2, d):
  30.     force = GRAVITY_CONSTANT / (d ** 2) + 3 # Calculate force using inverse square law
  31.     angle = math.atan2(y2 - y1, x2 - x1) # Calculate angle between points
  32.     return force * math.cos(angle) * -1, force * math.sin(angle) * -1 # Calculate x and y components of force
  33.  
  34. # Create list of points with random locations and velocities
  35. points = []
  36. for i in range(NUM_POINTS):
  37.     x = random.randint(RADIUS, WIDTH-RADIUS)
  38.     y = random.randint(RADIUS, HEIGHT-RADIUS)
  39.     angle = 2 * math.pi * random.random()
  40.     speed = MAX_SPEED
  41.     vx = speed * math.cos(angle)
  42.     vy = speed * math.sin(angle)
  43.     points.append({'x': x, 'y': y, 'vx': vx, 'vy': vy, 'speed': speed, 'lines': []})
  44.  
  45. # Define function for updating the positions of the points
  46. def update_points():
  47.     # Find nearest neighbors using sorted points list
  48.     canvas.delete('line')
  49.     did = set()
  50.     sorted_x = sorted(points, key=lambda p: p['x'])
  51.     sorted_y = sorted(points, key=lambda p: p['y'])
  52.     for i, point in enumerate(points):
  53.         min_dist = 9999999999
  54.         others = []
  55.         for ppp in (sorted_x, sorted_y):
  56.             iii = ppp.index(point)
  57.             for j in (iii-1, iii+1):
  58.                 try:
  59.                     others.append(ppp[j])
  60.                 except:
  61.                     0
  62.         for other in others:
  63.             d = distance(point['x'], point['y'], other['x'], other['y']) # Calculate the distance between the two circles
  64.             if d < min_dist:
  65.                 min_dist = d
  66.                 nearest = other
  67.         # Move point
  68.         point['x'] += point['vx']
  69.         point['y'] += point['vy']
  70.         # Apply repelling force from walls
  71.         if not (RADIUS < point['x'] < WIDTH - RADIUS and RADIUS < point['y'] < HEIGHT - RADIUS):
  72.             # Apply attracting force towards dead center
  73.             cx = WIDTH / 2
  74.             cy = HEIGHT / 2
  75.             dx = cx - point['x']
  76.             dy = cy - point['y']
  77.             dist = distance(point['x'], point['y'], cx, cy)
  78.             angle = math.atan2(-dy, -dx) # Calculate angle between point and center
  79.             point['vx'] += MAX_SPEED * math.cos(angle) * -1 # Apply force in x direction
  80.             point['vy'] += MAX_SPEED * math.sin(angle) * -1 # Apply force in y direction
  81.         else:
  82.             try:
  83.                 # Update velocities based on repelling force and steering force
  84.                 repel_x, repel_y = repel_force(point['x'], point['y'], nearest['x'], nearest['y'], min_dist)
  85.                 point['vx'] += repel_x
  86.                 point['vy'] += repel_y
  87.                 point['vx'] = (point['vx'] + (nearest['x'] - point['x']) / STEER) / 2
  88.                 point['vy'] = (point['vy'] + (nearest['y'] - point['y']) / STEER) / 2
  89.             except:
  90.                 0
  91.         # Keep velocity changes within maximum limit
  92.         speed = MAX_SPEED / math.sqrt(point['vx']**2 + point['vy']**2)
  93.         point['vx'] *= speed
  94.         point['vy'] *= speed
  95.         # Redraw point on canvas
  96.         canvas.coords(point['circle'], point['x']-RADIUS, point['y']-RADIUS, point['x']+RADIUS, point['y']+RADIUS)
  97.  
  98.         if min_dist < MIN_DISTANCE * 2 + RADIUS:
  99.             if not any(t in did for t in (id(point), id(nearest))):
  100.                 did.update([id(point), id(nearest)])
  101.                 # Update lines between points
  102.                 line = canvas.create_line(point['x'], point['y'], nearest['x'], nearest['y'], width=5, fill='lightgreen', tags='line')
  103.                 canvas.lower(line)
  104.  
  105.     # Call this function again after a delay
  106.     root.after(DELAY, update_points)
  107.  
  108. # Create circles on canvas for each point
  109. for point in points:
  110.     point['circle'] = canvas.create_oval(point['x']-RADIUS, point['y']-RADIUS, point['x']+RADIUS, point['y']+RADIUS, fill='yellow')
  111.  
  112. # Start animation loop
  113. update_points()
  114.  
  115. root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement