Advertisement
here2share

# tk_Rotating_Cube_Illusion.py

Feb 13th, 2024 (edited)
580
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.71 KB | None | 0 0
  1. # tk_Rotating_Cube_Illusion.py
  2.  
  3. ww, hh = 600, 600
  4.  
  5. from tkinter import *
  6. import math
  7. import random
  8. import copy
  9. from PIL import Image, ImageDraw, ImageTk, ImageChops
  10.  
  11. random.seed(0)
  12.  
  13. def update_cube_coordinates():
  14.     for i in range(8):
  15.         x, y, z = rotated_coords[i][:3]
  16.         coordinates[i] = get_coords(x , y, z)
  17.  
  18. def get_coords(x, y, z):
  19.     rxy = (x**2 + y**2)**(1/2)
  20.     rxz = (x**2 + z**2)**(1/2)
  21.     ryz = (y**2 + z**2)**(1/2)
  22.  
  23.     if x > 0 and y > 0:
  24.         txy = math.atan(y/x)
  25.     elif x > 0 and y < 0:
  26.         txy = 2*math.pi + math.atan(y/x)
  27.     elif x < 0 and y > 0:
  28.         txy = math.pi + math.atan(y/x)
  29.     elif x < 0 and y < 0:
  30.         txy = math.pi + math.atan(y/x)
  31.  
  32.     if z > 0 and x > 0:
  33.         txz = math.atan(x/z)
  34.     elif z > 0 and x < 0:
  35.         txz = 2*math.pi + math.atan(x/z)
  36.     elif z < 0 and x > 0:
  37.         txz = math.pi + math.atan(x/z)
  38.     elif z < 0 and x < 0:
  39.         txz = math.pi + math.atan(x/z)
  40.  
  41.     if y > 0 and z > 0:
  42.         tyz = math.atan(z/y)
  43.     elif y > 0 and z < 0:
  44.         tyz = 2*math.pi + math.atan(z/y)
  45.     elif y < 0 and z > 0:
  46.         tyz = math.pi + math.atan(z/y)
  47.     elif y < 0 and z < 0:
  48.         tyz = math.pi + math.atan(z/y)
  49.  
  50.     return x, y, z, rxy, rxz, ryz, txy, txz, tyz
  51.  
  52. def rotate_z(coord, t):
  53.     txy = coord[6] + t if coord[6] + t >= 0 else coord[6] + t + 2*math.pi
  54.     x = math.cos(txy) * coord[3]
  55.     y = math.sin(txy) * coord[3]
  56.     return get_coords(x, y, coord[2])
  57.  
  58. def rotate_y(coord, t):
  59.     txz = coord[7] + t if coord[7] + t >= 0 else coord[7] + t + 2*math.pi
  60.     z = math.cos(txz) * coord[4]
  61.     x = math.sin(txz) * coord[4]
  62.     return get_coords(x, coord[1], z)
  63.  
  64. def rotate_x(coord, t):
  65.     tyz = coord[8] + t if coord[8] + t >= 0 else coord[8] + t + 2*math.pi
  66.     y = math.cos(tyz) * coord[5]
  67.     z = math.sin(tyz) * coord[5]
  68.     return get_coords(coord[0], y, z)
  69.  
  70. rotation_speeds = {}
  71. def rotation():
  72.     rotation_speeds["X"] = random.uniform(0.02, 0.05) * random.choice((1, -1))
  73.     rotation_speeds["Y"] = random.uniform(0.02, 0.05) * random.choice((1, -1))
  74.     rotation_speeds["Z"] = random.uniform(0.02, 0.05) * random.choice((1, -1))
  75. rotation()
  76.  
  77. def alias_line(x1, y1, x2, y2):
  78.     num_squares = int(max(abs(x2 - x1), abs(y2 - y1))) or 1
  79.     for i in range(0, num_squares + 1, sq):
  80.         x = (x1 + i * (x2 - x1) // num_squares) // sq * sq
  81.         y = (y1 + i * (y2 - y1) // num_squares) // sq * sq
  82.         try:
  83.             if img.getpixel((x + 2, y + 2)) != (0, 0, 0):
  84.                 pos, color = xy[x, y, 'b']
  85.             else:
  86.                 pos, color = xy[x, y]
  87.             draw.rectangle(pos, outline=None, fill=color)
  88.         except:
  89.             0
  90. def plot():
  91.     for i in range(4):
  92.         alias_line(rotated_coords[i][0] * Vz/dd + Vx, rotated_coords[i][2] * Vz/dd + Vy,
  93.                  rotated_coords[(i + 1) % 4][0] * Vz/dd + Vx, rotated_coords[(i + 1) % 4][2] * Vz/dd + Vy)
  94.  
  95.         alias_line(rotated_coords[i + 4][0] * Vz/dd + Vx, rotated_coords[i + 4][2] * Vz/dd + Vy,
  96.                  rotated_coords[((i + 1) % 4) + 4][0] * Vz/dd + Vx, rotated_coords[((i + 1) % 4) + 4][2] * Vz/dd + Vy)
  97.  
  98.         alias_line(rotated_coords[i][0] * Vz/dd + Vx, rotated_coords[i][2] * Vz/dd + Vy,
  99.                  rotated_coords[i + 4][0] * Vz/dd + Vx, rotated_coords[i + 4][2] * Vz/dd + Vy)
  100.  
  101. ww, hh = 640, 640
  102. dd = 600
  103. sz = 100
  104. xSpeed = 5.7
  105. ySpeed = 7.8
  106. zSpeed = 9.9
  107. Vx = ww/2
  108. Vy = hh/2
  109. Vz = 1000
  110. bd = 10
  111. sq = 5
  112.  
  113. coordinates = [
  114.     get_coords(sz, sz, -sz), get_coords(-sz, sz, -sz), get_coords(-sz, sz, sz), get_coords(sz, sz, sz),
  115.     get_coords(sz, -sz, -sz), get_coords(-sz, -sz, -sz), get_coords(-sz, -sz, sz), get_coords(sz, -sz, sz)
  116. ]
  117.  
  118. win = Tk()
  119. win.title("# tk_Rotating_Cube_Illusion")
  120. win.geometry("%dx%d+%d+%d" %(ww, hh, 10, 10))
  121.  
  122. C = Canvas(win, width=ww, height=hh)
  123. C.pack()
  124.  
  125. img = Image.new("RGB", (ww, hh), "white")
  126. draw = ImageDraw.Draw(img)
  127.  
  128. for x in range(-2, 3):
  129.     for y in range(-2, 3):
  130.         C.create_text(x + ww // 2, y + 50, text="PRESS SPACEBAR", fill="white", font=("Arial", 40, "bold"), anchor="center", tag="hideable_text")
  131. C.create_text(ww // 2, 50, text="PRESS SPACEBAR", fill="red", font=("Arial", 40, "bold"), anchor="center", tag="hideable_text")
  132. def blink_text():
  133.     current_state = "normal" if C.itemcget("hideable_text", "state") == "hidden" else "hidden"
  134.     C.itemconfig("hideable_text", state=current_state)
  135.     C.tag_raise("hideable_text")
  136.  
  137.     win.after(1000, blink_text)
  138.  
  139. xy = {}
  140. for i in range(0, ww, sq):
  141.     for j in range(0, hh, sq):
  142.         pos = [i, j, i + sq - 1, j + sq - 1]
  143.         xy[i, j] = (pos, "white")
  144.         xy[i, j, 'b'] = (pos, "black")
  145.         draw.rectangle(pos, outline=None, fill=random.choice(('black', 'white')))
  146.  
  147. sp = 0.01
  148. rotate = {
  149.     "q": ("X", sp),
  150.     "w": ("X", -sp),
  151.     "e": ("Y", sp),
  152.     "a": ("Y", -sp),
  153.     "s": ("Z", sp),
  154.     "d": ("Z", -sp),
  155. }
  156.  
  157. def key_rotate(axis, t):
  158.     rotation_speeds[axis] = t
  159.  
  160. for k, (axis, t) in rotate.items():
  161.     win.bind(f"<Key-{k}>", lambda event, axis=axis, t=t: key_rotate(axis, t))
  162.    
  163. def toggle_pause(event):
  164.     global is_paused
  165.     is_paused = not is_paused
  166.  
  167. blink_text()
  168. win.bind("<space>", toggle_pause)
  169. is_paused = False
  170.  
  171. while True:
  172.     if not is_paused:
  173.         rotated_coords = []
  174.         for i in range(8):
  175.             rotated_coords.append(rotate_x(coordinates[i], rotation_speeds["X"]))
  176.             rotated_coords[i] = rotate_y(rotated_coords[i], rotation_speeds["Y"])
  177.             rotated_coords[i] = rotate_z(rotated_coords[i], rotation_speeds["Z"])
  178.  
  179.         plot()
  180.         update_cube_coordinates()
  181.                        
  182.         imgtk = ImageTk.PhotoImage(img)
  183.         C.create_image(0, 0, anchor=NW, image=imgtk)
  184.         C.tag_raise("hideable_text")
  185.  
  186.         at_wall = 0
  187.         if Vx < -bd:
  188.             xSpeed = abs(xSpeed)
  189.             at_wall = 1
  190.         elif Vx > ww + bd:
  191.             xSpeed = -abs(xSpeed)
  192.             at_wall = 1
  193.         if Vy < -bd:
  194.             ySpeed = abs(ySpeed)
  195.             at_wall = 1
  196.         elif Vy > hh + bd:
  197.             ySpeed = -abs(ySpeed)
  198.             at_wall = 1
  199.         if Vz < 800:
  200.             zSpeed = abs(zSpeed)
  201.             at_wall = 1
  202.         elif Vz > 1800:
  203.             zSpeed = -abs(zSpeed)
  204.             at_wall = 1
  205.            
  206.         if at_wall:
  207.             rotation()
  208.        
  209.         Vx += xSpeed
  210.         Vy += ySpeed
  211.         Vz += zSpeed
  212.    
  213.     win.update()
  214.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement