夜雨聆风学习资料网

ARTICLE · 1066605

节日源码:pygame国庆版5种类型烟花

节日源码:pygame国庆版5种类型烟花

Python,速成心法

敲代码,查资料,问度娘

练习,探索,总结,优化

博文创作不易,使用代码的过程中,如有疑问的地方,欢迎大家指正留言交流。喜欢的老铁可以多多点赞+收藏分享+置顶,小红牛在此表示感谢。

-------Pygame经典游戏-------

Python经典游戏:中国象棋1.0(pygame)

Python经典游戏:贪吃蛇(pygame+random)

Python经典游戏:打砖块(pygame+math)

Python经典游戏:扫雷(pygame+random)

Python经典游戏:简化版的QQ种菜游戏

pygame 版国庆烟花:带粒子系统、拖尾残影、5 种花型(牡丹/环形/柳树/心形/菊花),空格手动发射,鼠标点击就地炸开。

三个核心

部件
作用
Particle
一个粒子,管自己的运动+绘制
Rocket
升空火箭,到顶就调用 explode()
explode()
按花型批量生成粒子

拖尾残影(视觉关键)

fade.set_alpha(24)      # 每帧盖一层半透明黑screen.blit(fade, (0,0))

不是清屏,是让旧画面慢慢变暗。数字越小拖尾越长。

粒子物理

k = dt * 60             # 归一化帧率vx *= drag              # 阻力vy += gravity * k       # 重力life -= k               # 寿命
绘制时用 life/max_life 同时控制亮度和大小,比 alpha 快。
五种花型
牡丹:角度+速度都随机 → 均匀圆
环形:角度均匀 + Y轴压扁
柳树:只改物理(重力大、阻力大)
心形:参数方程直接当速度,Y 取负
菊花:内外两层,不同速度+颜色
保护:粒子超 2600 个就删最老的。

↓ 源码如下 ↓

# -*- coding: utf-8 -*-# @Author : 小红牛# 微信公众号:wdPythonimport pygameimport mathimport randomimport syspygame.init()W, H = 900620screen = pygame.display.set_mode((W, H))pygame.display.set_caption("国庆烟花 · pygame")clock = pygame.time.Clock()TAU = math.tau# 半透明黑层,每帧盖一次形成拖尾残影fade = pygame.Surface((W, H))fade.fill((000))fade.set_alpha(24)def get_font(size, bold=False):    for name in ("microsoftyahei""simhei""pingfangsc""hiraginosansgb",                 "notosanscjksc""wenquanyimicrohei""arialunicodems"):        path = pygame.font.match_font(name, bold=bold)        if path:            return pygame.font.Font(path, size)    return pygame.font.SysFont(None, size)FONT_BIG = get_font(52, bold=True)FONT_SMALL = get_font(18)PALETTE = [    (2558282), (25516860), (25523290), (120255140),    (90210255), (170140255), (255130200), (255255255),]class Particle:    __slots__ = ("x""y""vx""vy""color""life""max_life",                 "radius""gravity""drag")    def __init__(self, x, y, vx, vy, color, life, radius,                 gravity=0.055, drag=0.985):        self.x, self.y = x, y        self.vx, self.vy = vx, vy        self.color = color        self.life = self.max_life = life        self.radius = radius        self.gravity = gravity        self.drag = drag    def update(self, dt):        k = dt * 60        self.vx *= self.drag        self.vy *= self.drag        self.vy += self.gravity * k        self.x += self.vx * k        self.y += self.vy * k        self.life -= k    def draw(self, surf):        f = self.life / self.max_life        if f <= 0:            return        r = max(1int(self.radius * (0.35 + 0.65 * f)))        col = (int(self.color[0] * f), int(self.color[1] * f), int(self.color[2] * f))        pygame.draw.circle(surf, col, (int(self.x), int(self.y)), r)def explode(x, y, color, kind):    """按花型生成一批粒子"""    out = []    if kind == "peony":                      # 牡丹:均匀球形        for _ in range(random.randint(90130)):            a = random.uniform(0, TAU)            sp = random.uniform(0.56.2)            out.append(Particle(x, y, math.cos(a) * sp, math.sin(a) * sp,                                color, random.uniform(5595), 2.2))    elif kind == "ring":                     # 环形:带倾斜的圆环        n = 90        tilt = random.uniform(0.350.75)        for i in range(n):            a = TAU * i / n            sp = 5.4 + random.uniform(-0.250.25)            out.append(Particle(x, y, math.cos(a) * sp, math.sin(a) * sp * tilt,                                color, random.uniform(6085), 2.0))    elif kind == "willow":                   # 柳树:重力大、下坠慢        for _ in range(random.randint(7095)):            a = random.uniform(0, TAU)            sp = random.uniform(0.64.6)            out.append(Particle(x, y, math.cos(a) * sp, math.sin(a) * sp,                                color, random.uniform(90150), 2.4,                                gravity=0.14, drag=0.972))    elif kind == "heart":                    # 心形:参数方程采样        n = 110        for i in range(n):            t = TAU * i / n            px = 16 * math.sin(t) ** 3            py = (13 * math.cos(t) - 5 * math.cos(2 * t)                  - 2 * math.cos(3 * t) - math.cos(4 * t))            k = 0.36            out.append(Particle(x, y, px * k, -py * k, color,                                random.uniform(70100), 2.2))    else:                                    # 菊花:双层双色        c2 = random.choice(PALETTE)        for layer, (n, sp0, sp1) in enumerate(((702.03.2), (604.46.0))):            col = color if layer == 0 else c2            for _ in range(n):                a = random.uniform(0, TAU)                sp = random.uniform(sp0, sp1)                out.append(Particle(x, y, math.cos(a) * sp, math.sin(a) * sp,                                    col, random.uniform(65100), 2.1))    return outKINDS = ["peony""peony""ring""willow""heart""chrysanthemum"]class Rocket:    """升空的火箭,到高度后炸开"""    def __init__(self, x=None, target_y=None, color=None, kind=None):        self.x = x if x is not None else random.uniform(120, W - 120)        self.y = float(H + 10)        self.target_y = target_y if target_y is not None else random.uniform(70, H * 0.45)        self.color = color or random.choice(PALETTE)        self.kind = kind or random.choice(KINDS)        self.vy = -random.uniform(9.512.5)        self.vx = random.uniform(-0.80.8)    def update(self, dt):        k = dt * 60        self.x += self.vx * k        self.y += self.vy * k        self.vy += 0.045 * k        return self.vy >= -0.5 or self.y <= self.target_y    def draw(self, surf):        for i in range(16):            a = 1 - i / 6            r = max(1int(3 * a))            col = (int(255 * a), int(180 * a), int(60 * a))            pygame.draw.circle(                surf, col,                (int(self.x - self.vx * i * 0.6), int(self.y - self.vy * i * 0.6)), r)        pygame.draw.circle(surf, self.color, (int(self.x), int(self.y)), 3)        pygame.draw.circle(surf, (255255255), (int(self.x), int(self.y)), 1)def main():    particles, rockets = [], []    spawn_timer, next_spawn = 0.00.35    running = True    while running:        dt = min(clock.tick(60) / 1000.00.05)        for event in pygame.event.get():            if event.type == pygame.QUIT:                running = False            elif event.type == pygame.KEYDOWN:                if event.key == pygame.K_ESCAPE:                    running = False                elif event.key == pygame.K_SPACE:                    rockets.append(Rocket())            elif event.type == pygame.MOUSEBUTTONDOWN:                mx, my = event.pos                particles.extend(explode(mx, my, random.choice(PALETTE),                                         random.choice(KINDS)))        # 拖尾:整屏轻微变暗        screen.blit(fade, (00))        # 自动发射        spawn_timer += dt        if spawn_timer >= next_spawn:            spawn_timer = 0.0            next_spawn = random.uniform(0.350.95)            rockets.append(Rocket())        # 火箭        for rk in rockets[:]:            if rk.update(dt):                particles.extend(explode(rk.x, rk.y, rk.color, rk.kind))                rockets.remove(rk)            else:                rk.draw(screen)        # 粒子        for p in particles[:]:            p.update(dt)            if p.life <= 0 or p.x < -80 or p.x > W + 80 or p.y > H + 80:                particles.remove(p)            else:                p.draw(screen)        if len(particles) > 2600:                     # 防止堆积            del particles[:len(particles) - 2600]        # 文字        t = FONT_BIG.render("国 庆 快 乐"True, (25521590))        screen.blit(t, (W // 2 - t.get_width() // 2, H - 108))        s = FONT_SMALL.render("空格:发射    鼠标点击:就地炸开    ESC:退出",                              True, (210215235))        screen.blit(s, (W // 2 - s.get_width() // 2, H - 44))        pygame.display.flip()    pygame.quit()    sys.exit()if __name__ == "__main__":    main()

完毕!!感谢您的收看

--------★历史博文集合★--------

Python入门篇  进阶篇  视频教程  Py安装

py项目Python模块Python爬虫Json

Xpath正则表达式SeleniumEtreeCss

Gui程序开发TkinterPyqt5列表元组字典

数据可视化 matplotlib  词云图Pyecharts

海龟画图PandasBug处理电脑小知识

自动化脚本编程工具NumPy CSVWeb

Pygame  图像处理  机器学习数据库

相关学习资料