import tkinter as tk
import random
import time

WIDTH, HEIGHT = 400, 400
NUM_SNOWFLAKES = 200
GRAVITY = 0.2
FRICTION = 0.98

class Snowflake:
    def __init__(self, canvas):
        self.canvas = canvas
        self.x = random.uniform(0, WIDTH)
        self.y = random.uniform(0, HEIGHT)
        self.vx = 0
        self.vy = 0
        self.id = canvas.create_oval(self.x, self.y, self.x+2, self.y+2, fill="white", outline="")

    def update(self, shake_x, shake_y):
        # Apply shake force to the velocity
        self.vx += shake_x
        self.vy += shake_y

        # Apply gravity
        self.vy += GRAVITY

        # Move flake
        self.x += self.vx
        self.y += self.vy

        # Stay in bounds (wrap horizontally, bounce vertically)
        if self.x < 0:
            self.x = WIDTH
        elif self.x > WIDTH:
            self.x = 0

        # Top boundary: wrap to bottom
        if self.y < 0:
            self.y = HEIGHT

        # Bottom boundary: bounce
        if self.y > HEIGHT:
            self.y = HEIGHT
            self.vy *= -0.5  # bounce a bit

        # Friction to slow flakes gradually
        self.vx *= FRICTION
        self.vy *= FRICTION

        self.canvas.coords(self.id, self.x, self.y, self.x+2, self.y+2)

class SnowGlobe:
    def __init__(self, root):
        self.root = root
        self.canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg="skyblue")
        self.canvas.pack()
        self.snowflakes = [Snowflake(self.canvas) for _ in range(NUM_SNOWFLAKES)]

        # Track window motion
        self.prev_x = root.winfo_rootx()
        self.prev_y = root.winfo_rooty()
        self.shake_x = 0
        self.shake_y = 0

        root.bind("<Configure>", self.on_configure)
        self.update_animation()

    def on_configure(self, event):
        cur_x = self.root.winfo_rootx()
        cur_y = self.root.winfo_rooty()
        dx = cur_x - self.prev_x
        dy = cur_y - self.prev_y
        self.prev_x = cur_x
        self.prev_y = cur_y

        # A little scaling so larger movements cause bigger shake
        self.shake_x = dx * 0.2
        self.shake_y = dy * 0.2

    def update_animation(self):
        # Apply shake to each snowflake
        for snow in self.snowflakes:
            snow.update(self.shake_x, self.shake_y)

        # shake “dampens out” over time
        self.shake_x *= 0.9
        self.shake_y *= 0.9

        self.root.after(16, self.update_animation)

if __name__ == "__main__":
    root = tk.Tk()
    root.title("Snow Globe")
    globe = SnowGlobe(root)
    root.mainloop()
