py爱心代码

效果很好,具体效果请链接我抖音链接

 

import random
from math import sin, cos, pi, log
from tkinter import *
import pygame
import time
from PIL import Image, ImageTk

# ======= 爱心函数 =======
HEART_COLOR = "#ff69b4"

def heart_function(t, shrink_ratio, center_x, center_y):
    x = 16 * (sin(t) ** 3)
    y = -(13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t))
    x *= shrink_ratio
    y *= shrink_ratio
    x += center_x
    y += center_y - 30
    return int(x), int(y)

def scatter_inside(x, y, center_x, center_y, beta=0.15):
    ratio_x = - beta * log(random.random())
    ratio_y = - beta * log(random.random())
    dx = ratio_x * (x - center_x)
    dy = ratio_y * (y - center_y)
    return x - dx, y - dy

def shrink(x, y, center_x, center_y, ratio):
    force = -1 / (((x - center_x) ** 2 + (y - center_y) ** 2) ** 0.6)
    dx = ratio * force * (x - center_x)
    dy = ratio * force * (y - center_y)
    return x - dx, y - dy

def curve(p):
    return 2 * (2 * sin(4 * p)) / (2 * pi)

# ======= 爱心类 =======
class Heart:
    def __init__(self, center_x, center_y, shrink_ratio, generate_frame=20):
        self.center_x = center_x
        self.center_y = center_y
        self.shrink_ratio = shrink_ratio
        self._points = set()
        self._edge_diffusion_points = set()
        self._center_diffusion_points = set()
        self.all_points = {}
        self.build(2800)
        self.generate_frame = generate_frame
        for frame in range(generate_frame):
            self.calc(frame)

    def build(self, number):
        for _ in range(number):
            t = random.uniform(0, 2 * pi)
            x, y = heart_function(t, self.shrink_ratio, self.center_x, self.center_y)
            self._points.add((x, y))

        for _x, _y in list(self._points):
            for _ in range(3):
                x, y = scatter_inside(_x, _y, self.center_x, self.center_y, 0.05)
                self._edge_diffusion_points.add((x, y))

        point_list = list(self._points)
        for _ in range(5500):
            x, y = random.choice(point_list)
            x, y = scatter_inside(x, y, self.center_x, self.center_y, 0.17)
            self._center_diffusion_points.add((x, y))

    def calc_position(self, x, y, ratio):
        force = 1 / (((x - self.center_x) ** 2 + (y - self.center_y) ** 2) ** 0.520)
        dx = ratio * force * (x - self.center_x) + random.randint(-1, 1)
        dy = ratio * force * (y - self.center_y) + random.randint(-1, 1)
        return x - dx, y - dy

    def calc(self, generate_frame):
        ratio = 10 * curve(generate_frame / 10 * pi)
        halo_radius = int(6 + 6 * (1 + curve(generate_frame / 10 * pi)))
        halo_number = int(3800 + 4800 * abs(curve(generate_frame / 10 * pi) ** 2))
        all_points = []
        heart_halo_point = set()
        for _ in range(halo_number):
            t = random.uniform(0, 2 * pi)
            x, y = heart_function(t, self.shrink_ratio * 0.91, self.center_x, self.center_y)
            x, y = shrink(x, y, self.center_x, self.center_y, halo_radius)
            if (x, y) not in heart_halo_point:
                heart_halo_point.add((x, y))
                x += random.randint(-12, 12)
                y += random.randint(-12, 12)
                size = random.choice((1, 2, 2))
                all_points.append((x, y, size))
        for x, y in self._points:
            x, y = self.calc_position(x, y, ratio)
            size = random.randint(1, 3)
            all_points.append((x, y, size))
        for x, y in self._edge_diffusion_points:
            x, y = self.calc_position(x, y, ratio)
            size = random.randint(1, 2)
            all_points.append((x, y, size))
        for x, y in self._center_diffusion_points:
            x, y = self.calc_position(x, y, ratio)
            size = random.randint(1, 2)
            all_points.append((x, y, size))
        self.all_points[generate_frame] = all_points

    def render(self, canvas, frame):
        for x, y, size in self.all_points[frame % self.generate_frame]:
            canvas.create_rectangle(x, y, x + size, y + size, width=0, fill=HEART_COLOR)

# ======= LOVE雨滴 =======
class LoveRain:
    def __init__(self, canvas, width, height, cols=50, speed_range=(4,12), font_size=20):
        self.canvas = canvas
        self.width = width
        self.height = height
        self.cols = cols
        self.speed_range = speed_range
        self.font = ("Courier", font_size, "bold")
        self.colors = ["#ff69b4","#ffb6c1","#ffc0cb","#ff1493"]
        self.rains = []
        self._init_rains()

    def _init_rains(self):
        gap = self.width // self.cols
        for i in range(self.cols):
            for _ in range(2):
                x = i * gap + gap // 2
                y = random.randint(-self.height,0)
                speed = random.randint(*self.speed_range)
                text = random.choice(["L","O","V","E"])
                self.rains.append([x, y, speed, text, random.choice(self.colors)])

    def update(self):
        for rain in self.rains:
            rain[1] += rain[2]
            if rain[1] > self.height + 40:
                rain[1] = random.randint(-self.height,0)
                rain[3] = random.choice(["L","O","V","E"])
                rain[4] = random.choice(self.colors)

    def draw(self):
        for x, y, _, text, color in self.rains:
            self.canvas.create_text(x, y, text=text, fill=color, font=self.font)

# ======= 主绘制函数 =======
def draw(main, canvas, heart, start_time, love_rain, photos, photo_start_time, photo_interval, frame=0):
    canvas.delete('all')
    elapsed = time.time() - start_time

    if elapsed < photo_start_time:
        love_rain.update()
        love_rain.draw()
        heart.render(canvas, frame)
        canvas.create_text(canvas.winfo_width()//2, canvas.winfo_height()-30,
                           text="朱举修天天开心", fill="#ffb6c1", font=("Helvetica", max(20, canvas.winfo_width()//40), "bold"))
    else:
        photo_index = int((elapsed - photo_start_time)//photo_interval)
        if photo_index >= len(photos):
            photo_index = len(photos)-1
        canvas.create_image(canvas.winfo_width()//2, canvas.winfo_height()//2, image=photos[photo_index])

    main.after(60, draw, main, canvas, heart, start_time, love_rain, photos, photo_start_time, photo_interval, frame+1)

# ======= 入口 =======
if __name__ == '__main__':
    # 初始化音乐
    pygame.mixer.init()
    pygame.mixer.music.load(r"C:\Users\lenovo\Music\薛之谦 - 演员_H.mp3")  # 替换你的音乐路径
    pygame.mixer.music.play(-1)

    # 创建 Tk 窗口
    root = Tk()
    root.attributes("-fullscreen", True)
    root.bind("<Escape>", lambda e: root.destroy())

    SCREEN_WIDTH = root.winfo_screenwidth()
    SCREEN_HEIGHT = root.winfo_screenheight()
    CANVAS_CENTER_X = SCREEN_WIDTH / 2
    CANVAS_CENTER_Y = SCREEN_HEIGHT / 2
    IMAGE_ENLARGE = min(SCREEN_WIDTH, SCREEN_HEIGHT) / 57

    canvas = Canvas(root, bg='black')
    canvas.pack(fill=BOTH, expand=True)

    # 创建爱心和雨滴对象
    heart = Heart(CANVAS_CENTER_X, CANVAS_CENTER_Y, IMAGE_ENLARGE)
    LOVE_FONT_SIZE = max(12, SCREEN_WIDTH // 60)
    love_rain = LoveRain(canvas, SCREEN_WIDTH, SCREEN_HEIGHT, font_size=LOVE_FONT_SIZE)

    # 加载照片
    photo_files = [r"C:\Users\lenovo\Desktop\1.jpg", r"C:\Users\lenovo\Desktop\2.jpg", r"C:\Users\lenovo\Desktop\3.jpg"]  # 替换路径
    PHOTO_WIDTH = SCREEN_WIDTH // 2
    PHOTO_HEIGHT = SCREEN_HEIGHT // 2
    photos = []
    for f in photo_files:
        img = Image.open(f).resize((PHOTO_WIDTH, PHOTO_HEIGHT))
        photos.append(ImageTk.PhotoImage(img))

    # 照片显示时间
    photo_start_time = 261  # 秒(4分21秒)
    photo_interval = 3      # 每张照片显示间隔

    start_time = time.time()
    draw(root, canvas, heart, start_time, love_rain, photos, photo_start_time, photo_interval)
    root.mainloop()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值