谁懂啊!用代码表达浪漫,真的太戳人了✨
没有复杂的道具,没有华丽的辞藻,一行行代码、5000个彩色粒子,从四面八方奔赴而来,慢慢汇聚成一颗跳动的爱心,带着呼吸感、光晕和温柔的拖尾,把藏在心底的温柔,都藏进了屏幕里。
今天就带大家手把手实现「粒子汇聚爱心」效果,用Pygame+Numpy,零基础也能get的浪漫代码,不管是自己玩、做桌面壁纸,还是发给喜欢的人,都足够惊艳~
先看效果!心动预警💖
粒子从屏幕底部随机出现,带着淡淡的粉紫色光晕,缓缓向上移动,一点点靠近、汇聚,最终组成一颗完整的爱心;爱心会跟着呼吸轻轻缩放,每个粒子到达目标后,还会有细微的抖动,像在诉说温柔,移动过程中留下的拖尾,更添几分朦胧感。
小贴士:效果可直接作为桌面动态壁纸,也能导出成视频,发给在意的人,解锁专属浪漫~
核心工具&依赖
实现这个效果,只需要两个常用Python库,安装简单,新手也能快速上手:
安装命令(复制到终端执行即可):
完整代码|直接复制可运行
代码已全部优化、注释,关键步骤都标清了,不需要修改任何参数,复制粘贴到Python编辑器(PyCharm、VS Code都可以),运行就能看到效果👇
import pygameimport numpy as npimport random# 初始化 pygamepygame.init()# 屏幕设置(高清分辨率,效果更细腻)WIDTH, HEIGHT = 1200, 800screen = pygame.display.set_mode((WIDTH, HEIGHT))pygame.display.set_caption("粒子汇聚爱心")clock = pygame.time.Clock()# 颜色定义(接近截图的粉紫色系)BLACK = (0, 0, 0)PINK = (255, 105, 180) # 亮粉LIGHT_PINK = (255, 182, 193) # 淡粉PURPLE = (186, 85, 211) # 淡紫PALE_PURPLE = (220, 180, 220) # 淡粉紫# 爱心参数方程(经典数学公式)def heart_shape(t, scale=1, offset_x=0, offset_y=0): x = 16 * np.sin(t) ** 3 y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t) # 缩放 + 居中 + 垂直翻转(让爱心正立) return x * scale + offset_x, -y * scale + offset_y# 粒子类(集成呼吸、拖尾、光晕逻辑)class Particle: def __init__(self, target_x, target_y, global_scale): self.target_x = target_x self.target_y = target_y self.global_scale = global_scale # 引用全局呼吸缩放值 # 初始位置:屏幕底部随机(模拟从下方汇聚) self.x = random.randint(0, WIDTH) self.y = HEIGHT + random.randint(100, 300) # 物理属性 self.speed = random.uniform(0.8, 2.2) self.acceleration = 0.12 self.vx, self.vy = 0.0, 0.0 self.arrived = False # 视觉属性 self.base_color = random.choice([PINK, LIGHT_PINK, PURPLE, PALE_PURPLE]) self.size = random.randint(1, 4) self.alpha = random.uniform(0.7, 1.0) # 透明度 self.wobble_phase = random.uniform(0, np.pi * 2) # 粒子独立抖动相位 def update(self, current_scale): # 更新全局缩放引用(实现呼吸效果) self.global_scale = current_scale # 目标位置随爱心缩放同步变化 scaled_target_x = self.target_x * (self.global_scale / 12) # 基准scale=12 scaled_target_y = self.target_y * (self.global_scale / 12) if not self.arrived: # 计算方向向量 dx = scaled_target_x - self.x dy = scaled_target_y - self.y dist = np.sqrt(dx ** 2 + dy ** 2) if dist < 3: # 到达阈值(更宽松,汇聚更丝滑) self.arrived = True self.x = scaled_target_x self.y = scaled_target_y return # 归一化方向 + 加速度 dx /= dist dy /= dist self.vx += dx * self.acceleration self.vy += dy * self.acceleration # 限制最大速度 vel_mag = np.sqrt(self.vx ** 2 + self.vy ** 2) if vel_mag > self.speed: self.vx = (self.vx / vel_mag) * self.speed self.vy = (self.vy / vel_mag) * self.speed # 更新位置 self.x += self.vx self.y += self.vy else: # 到达后:独立呼吸抖动(不影响整体缩放) wobble_amt = 0.8 * np.sin(pygame.time.get_ticks() * 0.01 + self.wobble_phase) self.x = scaled_target_x + wobble_amt self.y = scaled_target_y + wobble_amt def draw(self, screen): # 绘制粒子本体(带透明度) surf = pygame.Surface((self.size * 2, self.size * 2), pygame.SRCALPHA) color = (*self.base_color, int(self.alpha * 255)) pygame.draw.circle(surf, color, (self.size, self.size), self.size) screen.blit(surf, (int(self.x) - self.size, int(self.y) - self.size)) # 绘制外围光晕(仅到达目标的粒子) if self.arrived: glow_surf = pygame.Surface((self.size * 4, self.size * 4), pygame.SRCALPHA) glow_color = (*LIGHT_PINK, int(self.alpha * 80)) # 低透明度光晕 pygame.draw.circle(glow_surf, glow_color, (self.size * 2, self.size * 2), self.size * 2) screen.blit(glow_surf, (int(self.x) - self.size * 2, int(self.y) - self.size * 2))# 生成爱心所有目标点def generate_heart_points(num_points=5000): t = np.linspace(0, 2 * np.pi, num_points) # 初始基准缩放(居中显示) return list(zip(*heart_shape(t, scale=12, offset_x=WIDTH // 2, offset_y=HEIGHT // 3)))# 主程序核心逻辑def main(): # 生成基础目标点 heart_points = generate_heart_points(num_points=5000) # 创建粒子列表(每个点对应一个粒子) particles = [Particle(x, y, 12.0) for x, y in heart_points] # 拖尾效果:创建专用缓存表面(黑色半透明,实现残留轨迹) trail_surface = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA) trail_surface.fill((*BLACK, 20)) # 透明度20:拖尾残留长度适中 # 呼吸动画参数 breath_phase = 0.0 breath_speed = 0.08 # 呼吸节奏 base_scale = 12.0 # 基础缩放 breath_range = 0.8 # 缩放幅度 running = True while running: # 控制帧率(60FPS,保证流畅) clock.tick(60) # 1. 事件处理(关闭窗口可退出) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 2. 呼吸缩放计算(正弦函数实现平滑呼吸) current_scale = base_scale + breath_range * np.sin(breath_phase) breath_phase += breath_speed # 3. 绘制拖尾(底层绘制,实现轨迹残留) screen.blit(trail_surface, (0, 0)) # 4. 更新并绘制所有粒子 for p in particles: p.update(current_scale) p.draw(screen) # 5. 刷新屏幕 pygame.display.flip() # 退出程序 pygame.quit()# 修正这行!!!前后都要有空格if __name__ == "__main__": main() # 这行必须缩进
关键效果拆解|新手也能看懂
不想深究代码?没关系!重点看这3个核心效果,知道它们的作用,就能轻松调整出自己喜欢的样子:
1. 爱心形状:数学公式的浪漫
用经典的爱心参数方程,通过Numpy计算出5000个目标点,这些点组成了爱心的轮廓;通过缩放和偏移,让爱心居中显示在屏幕上,还能通过调整scale参数,控制爱心的大小。
2. 粒子动效:奔赴的仪式感
每个粒子都有自己的初始位置(屏幕底部随机)、速度和颜色,它们会朝着自己对应的爱心目标点移动,到达后会轻微抖动;粒子的大小、速度、颜色都是随机的,让效果更自然、有层次感。
3. 呼吸+拖尾+光晕:氛围感神器
呼吸效果:通过正弦函数控制爱心的缩放,模拟呼吸的节奏,温柔又灵动;
拖尾效果:用半透明的黑色表面,让粒子移动后留下淡淡的轨迹,增加朦胧感;
光晕效果:粒子到达目标后,会有一圈淡粉色的光晕,让爱心更有光泽,氛围感拉满。
小技巧|自定义你的专属爱心
想让爱心更有个性?修改这几个参数就可以,新手也能轻松操作:
调整爱心大小:找到base_scale = 12.0,数值越大,爱心越大;
改变呼吸节奏:调整breath_speed = 0.08,数值越小,呼吸越慢;
更换颜色:修改颜色定义部分的RGB值,比如换成蓝色、红色,打造不同风格;
调整粒子数量:找到generate_heart_points(num_points=5000),数值越多,爱心越饱满(建议5000-10000)。
常见问题|避坑指南
运行中遇到问题?看看这两个最常见的情况,快速解决:
其实代码从来都不是冰冷的,它可以是浪漫的载体,是藏在细节里的温柔。
5000个粒子的奔赴,就像我们对生活、对在意的人的热爱,一点点靠近,一点点圆满。
赶紧复制代码,运行起来,把这份专属浪漫,留给自己,或者送给那个特别的人吧~
文末福利:关注公众号,回复「爱心粒子」,获取完整代码+效果动图+壁纸导出教程,轻松解锁更多玩法~,私信我也可以哦!
💬 评论区聊聊:你想用这段代码,送给谁?