import random
import tkinter as tk
from math import sin, cos, pi, log
from tkinter import Tk, Canvas
from PIL import Image, ImageTk
# 获取屏幕分辨率
root = Tk()
SCREEN_WIDTH = root.winfo_screenwidth()
SCREEN_HEIGHT = root.winfo_screenheight()
root.destroy()
# 画布尺寸设为屏幕大小
CANVAS_WIDTH = SCREEN_WIDTH
CANVAS_HEIGHT = SCREEN_HEIGHT
CANVAS_CENTER_X = CANVAS_WIDTH / 2
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2
IMAGE_ENLARGE = 18 # 增大放大比例,让爱心更大
# 蓝色渐变相关颜色定义
HEART_COLORS = [
"#0000CD", # 中蓝色
"#1E90FF", # 道奇蓝
"#87CEEB", # 天蓝色
"#B0E2FF", # 亮天蓝色
]
# 要显示的文字列表
TEXT_LIST = [
"他不折磨别人只折磨自己", "他喜欢装成熟", "年年康乐,岁岁满全", "我觉得我的十八岁有点逆生长",
"不要不开心,你做什么选择做什么决定我都支持你", "逆生长的18岁是23岁的同频,23岁的你是给我18岁的回礼", "你可以演我小弟啊 我当大哥罩着你", "有任何事情冲我来就可以",
"真心换真心", "宝宝你是我最可爱的宝宝", "获得了一段真挚的关系", "凌晨的经济舱 为爱冲锋的勋章!",
"缘为冰,我把他抱在怀里 冰化了,才发现缘分还在", "其实,该说的都说过了", "我送你三千万,千万要开心,千万要健康,千万要平安", "不要伤害一直以来无私帮助我的人"
]
# 存储已显示的文字ID
displayed_texts = []
# 当前显示的文字索引
current_text_index = 0
def heart_function(t, shrink_ratio: float = IMAGE_ENLARGE):
"""爱心函数生成器"""
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 += CANVAS_CENTER_X
y += CANVAS_CENTER_Y
return int(x), int(y)
def scatter_inside(x, y, beta=0.15):
"""在爱心内部随机散布点"""
ratio_x = -beta * log(random.random())
ratio_y = -beta * log(random.random())
dx = ratio_x * (x - CANVAS_CENTER_X)
dy = ratio_y * (y - CANVAS_CENTER_Y)
return x - dx, y - dy
def shrink(x, y, ratio):
"""缩小效果"""
force = -1 / (((x - CANVAS_CENTER_X) **2 + (y - CANVAS_CENTER_Y)** 2) **0.6)
dx = ratio * force * (x - CANVAS_CENTER_X)
dy = ratio * force * (y - CANVAS_CENTER_Y)
return x - dx, y - dy
def curve(p):
"""辅助曲线函数,控制爱心跳动的节奏"""
return 2 * (2 * sin(4 * p)) / (2 * pi)
class Heart:
"""爱心类,负责生成爱心的各种点集并处理动画效果"""
def __init__(self, generate_frame=20):
self._points = set() # 原始爱心点
self._edge_diffusion_points = set() # 边缘扩散点
self._center_diffusion_points = set() # 中心扩散点
self.all_points = {} # 所有点的集合,按帧存储
self.build(3000) # 增加点的数量
self.random_halo = 1000
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._points.add((x, y))
# 爱心内扩散
for _x, _y in list(self._points):
for _ in range(3):
x, y = scatter_inside(_x, _y, 0.05)
self._edge_diffusion_points.add((x, y))
point_list = list(self._points)
for _ in range(6000): # 增加中心扩散点数量
x, y = random.choice(point_list)
x, y = scatter_inside(x, y, 0.17)
self._center_diffusion_points.add((x, y))
@staticmethod
def calc_position(x, y, ratio):
# 计算位置,添加随机抖动
force = 1 / (((x - CANVAS_CENTER_X) **2 + (y - CANVAS_CENTER_Y)** 2) **0.520)
dx = ratio * force * (x - CANVAS_CENTER_X) + random.randint(-1, 1)
dy = ratio * force * (y - CANVAS_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(4 + 6 * (1 + curve(generate_frame / 10 * pi)))
halo_number = int(5000 + 7000 * 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, shrink_ratio=18.6) # 增大光环尺寸
x, y = shrink(x, y, halo_radius)
if (x, y) not in heart_halo_point:
heart_halo_point.add((x, y))
x += random.randint(-14, 14)
y += random.randint(-14, 14)
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, render_canvas, render_frame):
"""渲染爱心,使用蓝色渐变"""
frame_points = self.all_points[render_frame % self.generate_frame]
total_points = len(frame_points)
# 根据点在列表中的位置分配不同的蓝色
for i, (x, y, size) in enumerate(frame_points):
# 确保点在画布范围内
if 0 <= x < CANVAS_WIDTH and 0 <= y < CANVAS_HEIGHT:
color_index = int((i / total_points) * len(HEART_COLORS))
color = HEART_COLORS[min(color_index, len(HEART_COLORS) - 1)]
render_canvas.create_rectangle(x, y, x + size, y + size, width=0, fill=color, tags="heart")
def add_orderly_text(canvas):
"""按顺序添加文字到画布"""
global current_text_index
# 检查是否还有未显示的文字
if current_text_index < len(TEXT_LIST):
# 获取当前要显示的文字
text = TEXT_LIST[current_text_index]
# 随机位置(确保在屏幕范围内)
x = random.randint(50, CANVAS_WIDTH - 50)
y = random.randint(50, CANVAS_HEIGHT - 50)
# 随机字体大小
font_size = random.randint(12, 24)
# 创建文字并保存ID
text_id = canvas.create_text(
x, y,
text=text,
fill="white",
font=("SimHei", font_size),
tags="text"
)
displayed_texts.append(text_id)
# 索引加1,准备显示下一个文字
current_text_index += 1
# 1秒后再次添加文字
canvas.after(1000, add_orderly_text, canvas)
def draw(main: Tk, render_canvas: Canvas, render_heart: Heart, render_frame=0):
"""绘制函数,负责每一帧的绘制和动画更新"""
# 只清除爱心相关元素,保留文字
render_canvas.delete("heart")
# 绘制背景图片
if background_image_tk:
render_canvas.create_image(CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2, image=background_image_tk, tags="heart")
# 绘制爱心(添加heart标签)
render_heart.render(render_canvas, render_frame)
# 更新帧
main.after(160, draw, main, render_canvas, render_heart, (render_frame + 1) % render_heart.generate_frame)
if __name__ == '__main__':
root = Tk()
root.title("全屏跳动的爱心与文字")
root.attributes('-fullscreen', True) # 设置为全屏模式
root.bind("<Escape>", lambda e: root.destroy()) # 按ESC键退出全屏
# 加载背景图片并调整为屏幕大小
background_image_tk = None
try:
# 请将此路径替换为你自己的图片路径
background_image = Image.open("sea.png")
# 调整图片大小以适应屏幕
background_image = background_image.resize((CANVAS_WIDTH, CANVAS_HEIGHT), Image.LANCZOS)
background_image_tk = ImageTk.PhotoImage(background_image)
except Exception as e:
print(f"无法加载背景图片: {e}")
print("将使用黑色背景")
canvas = Canvas(root, bg='black', height=CANVAS_HEIGHT, width=CANVAS_WIDTH)
canvas.pack()
heart = Heart()
# 添加说明文字
if background_image_tk:
canvas.create_text(CANVAS_WIDTH / 2, CANVAS_HEIGHT - 30,
text="爱心跳动中... 文字将按顺序出现并保留... 按ESC键退出",
fill="white", font=("SimHei", 14), tags="text")
# 开始按顺序添加文字
add_orderly_text(canvas)
# 开始绘制
draw(root, canvas, heart)
root.mainloop()修改代码,使文字按顺序出现,并只出现一次,文字出现后不消失
最新发布