Files
INF6B/simulations/donut.c/tktcl.py
rattatwinko d0eaabdd87 some new stuff.
idk its all pretty fun! some C++ too!
2025-10-15 11:16:51 +02:00

114 lines
3.1 KiB
Python

import tkinter as tk
import math
# Torus parameters
theta_spacing = 0.07
phi_spacing = 0.02
R1 = 1
R2 = 2
K2 = 5
chars = ".,-~:;=!*#$@" # luminance chars
# Base character grid (like "screen resolution")
screen_width = 80
screen_height = 24
# Tkinter setup
root = tk.Tk()
root.title("Spinning Torus Demo")
# Get window size and calculate scaling
window_width = 800
window_height = 400
root.geometry(f"{window_width}x{window_height}")
# Calculate character cell size to fit screen dimensions
cell_width = window_width // screen_width
cell_height = window_height // screen_height
font_size = min(cell_width, cell_height)
font = ("Courier", font_size)
canvas = tk.Canvas(root, width=window_width, height=window_height, bg="black")
canvas.pack()
# Pre-create text items for the character grid
text_items = []
for y in range(screen_height):
row = []
for x in range(screen_width):
item = canvas.create_text(
x*cell_width, y*cell_height,
text=' ',
anchor='nw',
fill='white',
font=font
)
row.append(item)
text_items.append(row)
# Calculate K1 based on screen width
K1 = screen_width * K2 * 3 / (8 * (R1 + R2))
def render_frame(A, B):
cosA = math.cos(A)
sinA = math.sin(A)
cosB = math.cos(B)
sinB = math.sin(B)
output = [[' ' for _ in range(screen_height)] for _ in range(screen_width)]
zbuffer = [[0 for _ in range(screen_height)] for _ in range(screen_width)]
theta = 0
while theta < 2 * math.pi:
costheta = math.cos(theta)
sintheta = math.sin(theta)
phi = 0
while phi < 2 * math.pi:
cosphi = math.cos(phi)
sinphi = math.sin(phi)
circlex = R2 + R1 * costheta
circley = R1 * sintheta
x = circlex * (cosB * cosphi + sinA * sinB * sinphi) - circley * cosA * sinB
y = circlex * (sinB * cosphi - sinA * cosB * sinphi) + circley * cosA * cosB
z = K2 + cosA * circlex * sinphi + circley * sinA
ooz = 1 / z
xp = int(screen_width / 2 + K1 * ooz * x)
yp = int(screen_height / 2 - K1 * ooz * y)
L = cosphi * costheta * sinB - cosA * costheta * sinphi - sinA * sintheta + cosB * (cosA * sintheta - costheta * sinA * sinphi)
if L > 0:
if 0 <= xp < screen_width and 0 <= yp < screen_height:
if ooz > zbuffer[xp][yp]:
zbuffer[xp][yp] = ooz
luminance_index = int(L * 8)
if luminance_index >= len(chars):
luminance_index = len(chars) - 1
output[xp][yp] = chars[luminance_index]
phi += phi_spacing
theta += theta_spacing
# Update Tkinter canvas
for y in range(screen_height):
for x in range(screen_width):
canvas.itemconfigure(text_items[y][x], text=output[x][y])
# Animation loop
A = 0
B = 0
def animate():
global A, B
render_frame(A, B)
A += 0.07
B += 0.03
root.after(30, animate)
animate()
root.mainloop()