# tk_text2physics.py import tkinter as tk import random import math root = tk.Tk() root.title("# tk_text2physics") canvas = tk.Canvas(root, width=600, height=600, bg='#333333') canvas.pack() letters_x = [] letters_y = [] letters_vx = [] letters_vy = [] letters_angle = [] letters_av = [] letters_char = [] letter_chars = list("QWERTYUIOPASDFGHJKLZXCVBNM1234567890") def apply_force(i, fx, fy): letters_vx[i] += fx letters_vy[i] += fy def update_letter(i): letters_vy[i] += 0.5 letters_x[i] += letters_vx[i] letters_y[i] += letters_vy[i] letters_angle[i] += letters_av[i] letters_vx[i] *= 0.98 letters_vy[i] *= 0.98 letters_av[i] *= 0.92 if abs(letters_vx[i]) < 0.01: letters_vx[i] = 0 if abs(letters_vy[i]) < 0.01: letters_vy[i] = 0 if abs(letters_av[i]) < 0.001: letters_av[i] = 0 if letters_y[i] > 570: letters_y[i] = 570 if abs(letters_vy[i]) < 0.5: letters_vy[i] = 0 else: letters_vy[i] *= -0.4 letters_av[i] = letters_av[i] * 0.4 + letters_vx[i] * 0.05 if letters_x[i] < 30: letters_x[i] = 30 letters_vx[i] *= -0.4 letters_av[i] *= 0.6 if letters_x[i] > 570: letters_x[i] = 570 letters_vx[i] *= -0.4 letters_av[i] *= 0.6 def check_collision(i, j): dx = letters_x[j] - letters_x[i] dy = letters_y[j] - letters_y[i] dist = math.sqrt(dx*dx + dy*dy) if dist < 40 and dist > 0: nx = dx / dist ny = dy / dist dvx = letters_vx[j] - letters_vx[i] dvy = letters_vy[j] - letters_vy[i] dot = dvx * nx + dvy * ny if dot < 0: impulse = -1.2 * dot / 2 letters_vx[i] -= impulse * nx letters_vy[i] -= impulse * ny letters_vx[j] += impulse * nx letters_vy[j] += impulse * ny tangent_vel_i = -ny * letters_vx[i] + nx * letters_vy[i] tangent_vel_j = -ny * letters_vx[j] + nx * letters_vy[j] torque_i = tangent_vel_j * 0.015 torque_j = tangent_vel_i * 0.015 letters_av[i] += torque_i letters_av[j] += torque_j letters_av[i] *= 0.7 letters_av[j] *= 0.7 overlap = 40 - dist if letters_y[i] < letters_y[j]: letters_y[i] -= 3 else: letters_y[j] -= 3 letters_x[i] -= nx * overlap * 0.5 letters_y[i] -= ny * overlap * 0.5 letters_x[j] += nx * overlap * 0.5 letters_y[j] += ny * overlap * 0.5 def attract_letters(): for i in range(len(letters_x)): for j in range(i+1, len(letters_x)): dx = letters_x[j] - letters_x[i] dy = letters_y[j] - letters_y[i] dist = math.sqrt(dx*dx + dy*dy) if dist > 0 and dist < 150: force = 0.02 / (dist * dist + 1) fx = (dx / dist) * force fy = (dy / dist) * force apply_force(i, fx, fy) apply_force(j, -fx, -fy) def update(): canvas.delete('all') attract_letters() for i in range(len(letters_x)): update_letter(i) for i in range(len(letters_x)): for j in range(i+1, len(letters_x)): check_collision(i, j) for i in range(len(letters_x)): canvas.create_text(letters_x[i], letters_y[i], text=letters_char[i], font=('Arial', 50, 'bold'), fill='white', angle=math.degrees(letters_angle[i])) root.after(16, update) def spawn_letter(): if len(letters_x) < len(letter_chars): letters_x.append(random.randint(50, 550)) letters_y.append(-20) letters_vx.append(0) letters_vy.append(0) letters_angle.append(0) letters_av.append(0) letters_char.append(letter_chars[len(letters_x) - 1]) root.after(500, spawn_letter) def reset(event): letters_x.clear() letters_y.clear() letters_vx.clear() letters_vy.clear() letters_angle.clear() letters_av.clear() letters_char.clear() root.bind('', reset) spawn_letter() update() root.mainloop()