首页 / 资讯中心 / 文章详情

Python+Pygame零基础烟花动画:粒子系统与游戏循环实战

Python+Pygame零基础烟花动画:粒子系统与游戏循环实战 ★ FEATURED ARTICLE
简介这份资源面向对Python图形编程感兴趣的初学者与爱好者围绕Pygame库讲解如何从零搭建一个带音效的新年烟花动画程序帮助读者理解粒子系统、图形界面渲染与事件循环等基础概念。压缩包内共1个docx文档约16KB以图文与代码示例结合的方式组织内容便于边看边练。文档从环境准备讲起逐步展开粒子类的属性设计、烟花发射与爆炸逻辑、颜色随机配置以及背景音乐的加载与循环播放并给出可直接运行的完整代码读者可据此调整粒子数量、发射频率与音乐路径做出个性化的节日烟花展示。目前已有140人学习适合希望以趣味项目入门Pygame、提升图形界面应用处理能力的开发者参考实践。1. 零基础也能写烟花Python 加 Pygame 到底能做出什么你有没有过这种经历刷到别人用代码做的粒子动画满屏烟花炸开底下评论都在喊“大佬”你心里痒了一下但马上又觉得“这肯定很难我连 Python 都没装明白”。其实我第一次接触 Pygame 的时候也是这个反应觉得图形界面、动画、音效这些东西离零基础的人特别远。但真相是你只需要会一点点 Python 基础语法就能让屏幕上出现属于你自己的烟花。这份资源要带你做的事非常具体用 Python 配合 Pygame 这个库从零写出一段能运行的新年烟花动画。它会爆炸、会散开、会慢慢消失还能配上背景音乐。你不需要先学什么高深数学也不需要美术功底代码里所有效果都是靠“粒子”这个小东西堆出来的。适合谁适合刚学完 Python 基础、想找个看得见摸得着的项目练手的人适合想给节日加点仪式感、又不想只会调库的人也适合那些被“图形界面”四个字吓住、其实连窗口都没创建过的纯新手。这一章不写代码只帮你把心里那层“我不行”的膜捅破。2. 先搞懂它在干嘛烟花不是画出来的是“粒子”堆出来的2.1 为什么值得学 Pygame它把“画图”变成了“摆积木”很多新手一听图形编程脑子里浮现的是密密麻麻的坐标公式和颜色代码。Pygame 的好处恰恰是它不逼你从底层造轮子。你可以把它想象成一盒数字积木屏幕是一个画布你往上面放圆、放方块、放图片每一帧擦掉重画连续起来就是动画。烟花效果听起来玄学拆开看就是一堆小圆点每个小圆点有自己的位置、速度、颜色和寿命。你让它们从同一个点出发朝不同方向飞飞着飞着速度慢下来寿命到了就消失——这就是爆炸。我建议你先别管什么“粒子系统”这种术语。你就记住一句话一个粒子就是一个带属性小圆点烟花就是一百个小圆点同时往外跑。Pygame 负责把这些小圆点按你定的规则画到屏幕上每秒画 60 次你的眼睛就看到了流畅动画。音效部分更简单加载一个音频文件让它在程序启动时循环播放就行。你不需要懂音频编码只需要告诉 Pygame 文件在哪。2.2 为什么用“类”来写不写类也能跑但写了类你才看得懂原始代码里出现了Particle类和Firework类。零基础的人看到class就头大这很正常。但你换个角度想如果不用类你得为每一个小圆点单独写一堆变量100 个粒子就是 100 套x1, y1, speed1, x2, y2, speed2...写到第十个你就乱了。类的意义是把“一个粒子该有的东西”打包成一个模板用的时候直接复制这个模板改改初始值就行。Particle类管三件事自己在哪x, y、自己长什么样颜色、大小、自己怎么动角度、速度、寿命。Firework类管的是“一发烟花”它先有一个上升的白点等这个白点飞到一定高度就原地炸出 100 个彩色粒子。主循环则像一个导演每帧问所有烟花“你们更新了吗画出来了吗”然后擦掉旧画面画上新画面。你不需要一次看懂所有细节先知道这三个角色各干各的后面写代码时就不会迷路。2.3 第一个能跑的例子从空窗口到一朵烟花在写完整烟花之前你先跑通一个最小版本打开一个黑色窗口在中间画一个白色圆点让它自己慢慢往上飞。这一步跑通了后面加爆炸、加颜色、加音效都是在这个骨架上挂东西。import pygame import random import math # 初始化 Pygame任何 Pygame 程序的第一步 pygame.init() # 设置窗口大小宽 800高 600 screen_width, screen_height 800, 600 screen pygame.display.set_mode((screen_width, screen_height)) # 定义一个白色RGB 三个值都是 255 WHITE (255, 255, 255) BLACK (0, 0, 0) # 创建一个最简单的粒子位置在屏幕底部中间速度向上 x screen_width // 2 y screen_height speed 5 # 时钟对象用来控制帧率 clock pygame.time.Clock() running True while running: # 处理关闭窗口事件 for event in pygame.event.get(): if event.type pygame.QUIT: running False # 更新位置y 减小就是往上飞 y - speed # 填充背景擦掉上一帧 screen.fill(BLACK) # 画一个半径 4 的白色圆点 pygame.draw.circle(screen, WHITE, (int(x), int(y)), 4) # 刷新屏幕让画的东西显示出来 pygame.display.flip() # 限制每秒 60 帧不然飞太快 clock.tick(60) pygame.quit()这段代码里pygame.init()是开机键set_mode是开窗口screen.fill(BLACK)是每帧擦黑板pygame.draw.circle是画圆pygame.display.flip()是把画好的东西推到你眼前。clock.tick(60)是节拍器让循环每秒跑 60 次。你运行之后会看到一个白点从底部往上飘飘出屏幕就没了。这就是烟花的“上升阶段”。把speed改大一点它就飞得快把半径改大它就变胖。所有参数都是你说了算。提示如果运行报错说找不到 pygame先在命令行里执行pip install pygame。装完之后再跑一次窗口应该就出来了。3. 把一朵烟花拆开写粒子类、爆炸逻辑和主循环怎么配合3.1 粒子类给每个小圆点一张身份证上一章的白点只有一个所以用两个变量x和y就够了。但爆炸要同时管 100 个点每个点的飞行方向、速度、颜色、寿命都不一样。这时候就需要Particle类来当模板。你把它理解成一张身份证每个粒子出生时领一张上面写着“我从哪出发、我往哪个角度飞、我飞多快、我什么颜色、我还能活多久”。class Particle: def __init__(self, x, y, color): self.x x self.y y self.color color # 粒子大小随机 4 到 7 像素 self.size random.randint(4, 7) # 寿命初始 25 帧每帧减 1 self.life 25 # 飞行角度0 到 2π 之间随机 self.angle random.uniform(0, 2 * math.pi) # 飞行速度2 到 5 之间随机 self.speed random.uniform(2, 5) def move(self): # 根据角度和速度更新 x、y self.x self.speed * math.cos(self.angle) self.y - self.speed * math.sin(self.angle) # 每帧寿命减 1 self.life - 1 # 速度乘以 0.95模拟空气阻力越飞越慢 self.speed * 0.95 def draw(self): # 只有还活着的粒子才画出来 if self.life 0: pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.size)__init__是出生设置move是每帧移动draw是每帧画自己。math.cos和math.sin负责把角度换算成横向和纵向的移动量你不需要手算三角函数只要知道角度随机就是往四面八方飞。speed * 0.95这一句是让粒子飞出去之后慢慢减速看起来更自然不然它们会像子弹一样直线飞走。life减到 0 以下就不再画粒子就“消失”了。3.2 烟花类先上升再爆炸有了粒子模板接下来写Firework类。它管两件事第一先造一个白色粒子当“引线”让它从屏幕底部往上飞第二当这个白点飞到一定高度就原地生成 100 个彩色粒子然后把白点删掉。这个“先上升后爆炸”的逻辑就是烟花的核心节奏。class Firework: def __init__(self): self.particles [] # 爆炸颜色从红、绿、蓝里随机选一个 self.explosion_color random.choice([(255, 0, 0), (0, 255, 0), (0, 0, 255)]) def launch(self): # 在屏幕底部随机横向位置生成一个白色上升粒子 self.particles.append( Particle(random.randint(0, screen_width), screen_height, WHITE)) def explode(self): # 以当前白点的位置为中心炸出 100 个彩色粒子 for _ in range(100): self.particles.append( Particle(self.particles[0].x, self.particles[0].y, self.explosion_color)) # 删掉作为引线的白点 del self.particles[0] def update(self): # 如果没有任何粒子这发烟花结束 if not self.particles: return False for particle in self.particles[:]: particle.move() particle.draw() # 寿命用完就移除 if particle.life 0: self.particles.remove(particle) # 如果只剩引线白点并且它飞到了屏幕上半部分就爆炸 if len(self.particles) 1 and self.particles[0].y 100: self.explode() return Truelaunch只造一个白点explode一口气造 100 个彩色点update每帧负责移动、画图、清理死掉的粒子并判断引线是否该炸。self.particles[:]是复制一份列表再遍历这样你在循环里删除元素不会出错。y 100是爆炸高度数字越小炸得越高你可以改成 200 让它低一点或者改成 50 让它更高。3.3 主循环让烟花自己冒出来最后把主循环补全。主循环要做四件事处理退出和按键事件、更新所有烟花、随机生成新烟花、刷新屏幕。原始代码里有一个random.random() 0.05的判断意思是每一帧有 5% 的概率自动放一朵新烟花。你也可以按空格键手动加一朵。fireworks [Firework()] clock pygame.time.Clock() running True while running: for event in pygame.event.get(): if event.type pygame.QUIT: running False elif event.type pygame.KEYDOWN and event.key pygame.K_SPACE: # 按空格键手动加一朵烟花 fireworks.append(Firework()) screen.fill(BLACK) for firework in fireworks[:]: if not firework.update(): fireworks.remove(firework) # 每帧 5% 概率自动生成新烟花 if random.random() 0.05: fireworks.append(Firework()) fireworks[-1].launch() pygame.display.flip() clock.tick(60) pygame.quit()fireworks[:]同样是复制列表再遍历避免删除时出错。fireworks[-1].launch()是让刚加进来的烟花先发射引线。你运行之后会看到黑色夜空里不断有白点上升然后炸成红绿蓝的粒子雨。如果觉得烟花太少把0.05改成0.1如果觉得太多改成0.02。所有参数都在你手里。3.4 加上音效一行代码让气氛到位音效部分比你想的简单。你只需要准备一个 mp3 文件放在项目文件夹里然后在pygame.init()之后加两行pygame.mixer.music.load(new_year_music.mp3) pygame.mixer.music.play(-1)load是告诉 Pygame 文件在哪play(-1)里的-1表示无限循环。如果文件不在当前目录就写完整路径。如果运行时报错说音频设备忙先确认没有其他程序占用声卡或者把pygame.mixer.init()单独写一行放在pygame.init()后面。音效不是必须的但加上之后烟花炸开的瞬间配合音乐感觉完全不一样。4. 新手最容易翻车的几个地方避坑与排查4.1 窗口一闪而过或者直接卡死现象运行代码后窗口闪一下就没了或者一直黑屏转圈。原因最常见的是主循环里忘了写pygame.event.get()导致系统事件堆积窗口无响应。另一个可能是while循环里没有clock.tick()帧率跑到几千电脑扛不住。解决检查主循环里有没有事件处理有没有clock.tick(60)。如果窗口闪退在pygame.quit()之前加一句input()或者用try/except把报错打印出来。4.2 粒子飞出去不消失越积越多现象烟花炸完之后粒子一直留在屏幕上或者程序越跑越卡。原因Particle的life没有减到 0 以下或者Firework.update里没有把life 0的粒子移除。解决确认move方法里有self.life - 1确认update里有if particle.life 0: self.particles.remove(particle)。如果还是卡把爆炸粒子数从 100 降到 50或者把clock.tick(60)改成clock.tick(30)。4.3 音乐文件加载报错现象运行到pygame.mixer.music.load时提示找不到文件或格式不支持。原因路径写错了或者文件不是 mp3/ogg 格式。解决把音乐文件和 Python 脚本放在同一个文件夹文件名不要用中文和空格。如果还是不行换一个标准的 mp3 文件试试。注意pygame.mixer对某些高码率文件支持不好尽量用普通音质。4.4 爆炸位置不对烟花在屏幕外炸了现象只看到白点飞上去没看到爆炸或者爆炸在屏幕顶部外面。原因explode的判断条件是self.particles[0].y 100如果你的屏幕高度不是 600或者引线速度太快白点可能在到达 100 之前就飞出屏幕了。解决把y 100改成y screen_height // 3让爆炸高度跟着屏幕走。或者把引线速度调慢在launch里把Particle的速度参数改小。4.5 按空格键没反应现象想手动加烟花但按空格没效果。原因事件判断写成了event.type pygame.KEYDOWN但没检查event.key或者窗口没有获得焦点。解决确认代码是event.type pygame.KEYDOWN and event.key pygame.K_SPACE。如果还是没反应点一下窗口标题栏让它获得焦点再按空格。5. 下一步学什么从一朵烟花到一场烟花秀你现在已经跑通了最基础的版本一个窗口、一朵烟花、爆炸粒子、可选音效。接下来怎么继续我按自己的学习顺序给你一条路。第一步把爆炸粒子数从 100 改成 200看看电脑卡不卡卡的话就学会用clock.tick降帧率。第二步给Particle加一个gravity属性在move里让self.y gravity粒子就会往下落更像真实烟花。第三步把爆炸颜色改成渐变比如从黄色过渡到红色方法是让粒子的颜色随寿命变化在draw里根据self.life算 RGB 值。再往后你可以尝试一次发射多朵烟花让它们在不同高度爆炸。原始代码里fireworks列表可以同时装很多朵你只需要在launch时给每朵烟花一个随机的目标高度。音效方面可以准备多个爆炸音效在explode的时候用pygame.mixer.Sound播放而不是一直循环背景音乐。如果你想让烟花有拖尾效果可以在每帧画粒子之前把上一帧的屏幕稍微变暗而不是完全涂黑这样粒子移动会留下残影。下面这张表是我建议的练习顺序和对应改动点你可以照着一条条试练习目标改哪里预期效果烟花更多主循环random.random() 0.05改成0.1屏幕上同时有多朵烟花爆炸更大explode里range(100)改成range(200)粒子更密但可能掉帧粒子下落Particle加self.gravity 0.1move里self.y self.gravity爆炸后粒子往下飘颜色渐变draw里根据self.life调整颜色值粒子从亮变暗手动控制按空格加烟花按方向键改爆炸高度互动感更强我第一次写这个烟花的时候粒子飞出去就再也不回来屏幕上白点越积越多最后卡成幻灯片。后来才发现是忘了在update里删掉寿命耗尽的粒子。从那以后我每次写粒子系统都强制先写“出生、移动、死亡”这三步再写画图。这个习惯帮我省了很多后悔药。希望你也从这朵小烟花开始把图形编程的门推开。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站