夜雨聆风学习资料网

ARTICLE · 1060210

节日源码:pygame版嫦娥奔月动画

节日源码:pygame版嫦娥奔月动画

Python,速成心法

敲代码,查资料,问度娘

练习,探索,总结,优化

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

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

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

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

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

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

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

pygame 版嫦娥奔月动画:嫦娥用几何图形分层绘制:飘带、裙摆(正弦摆动)、水袖、发髻、发簪,整体沿贝塞尔曲线从画面外飞向月亮,并伴随金色粒子。

两阶段:预生成贴图(背景/光晕/云/星)→ 主循环拼接
柔光贴图:从外到内画同心圆,透明度递增,得到径向渐变。
嫦娥绘制:几何分层,从后往前
柔光 → 飘带 → 裙摆 → 上身 → 腰带 → 手臂 → 水袖 → 脖子 → 后发 → 脸 → 发髻 → 眼睛
所有坐标经 P(x,y) = (cx + x*scale, cy + y*scale),改 scale 整体缩放。
飘动感:飘带和裙摆的每个点加 sin(t*频率 + 位置) 偏移。
飞行路径:二次贝塞尔
B(t) = (1-t)²P0 + 2(1-t)t·P1 + t²P2

P0 起点(画面外),P1 控制点(决定弧度),P2 终点(月亮旁)

飞远效果:scale = lerp(1.15, 0.62, progress) —— 越飞越小。
跟随粒子:用 while 补足粒子,SPARK.set_alpha() 复用同一张贴图淡出。
云:预生成一张低透明度椭圆叠加图,横向平移,出界回绕。

↓ 源码如下 ↓

# -*- coding: utf-8 -*-# @Author : 小红牛# 微信公众号:wdPythonimport pygameimport mathimport randomimport syspygame.init()W, H = 960640screen = pygame.display.set_mode((W, H))pygame.display.set_caption("嫦娥奔月 · 中秋")clock = pygame.time.Clock()TAU = math.taudef lerp(a, b, t):    return a + (b - a) * tdef 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_TITLE = get_font(36, bold=True)FONT_TIP = get_font(18)# ───────── 资源预生成 ─────────def make_gradient(w, h, top, bottom):    surf = pygame.Surface((w, h))    for y in range(h):        f = y / max(1, h - 1)        col = tuple(int(lerp(top[i], bottom[i], f)) for i in range(3))        pygame.draw.line(surf, col, (0, y), (w, y))    return surfdef make_glow(radius, color, strength=120, power=2.2):    """径向柔光"""    size = radius * 2    surf = pygame.Surface((size, size), pygame.SRCALPHA)    for r in range(radius, 0, -1):        f = 1 - r / radius        a = int(strength * (f ** power))        pygame.draw.circle(surf, (*color, a), (radius, radius), r)    return surfdef make_spark(size=28, color=(255240200)):    """粒子光点"""    surf = pygame.Surface((size, size), pygame.SRCALPHA)    c = size // 2    for r in range(c, 0, -1):        a = int(255 * (1 - r / c) ** 2)        pygame.draw.circle(surf, (*color, a), (c, c), r)    return surfdef make_cloud(w, h, tint=(180195235)):    surf = pygame.Surface((w, h), pygame.SRCALPHA)    for _ in range(24):        cx = random.uniform(w * 0.15, w * 0.85)        cy = random.uniform(h * 0.3, h * 0.7)        rx = random.uniform(w * 0.10, w * 0.24)        ry = random.uniform(h * 0.20, h * 0.40)        pygame.draw.ellipse(surf, (*tint, random.randint(616)),                            (cx - rx, cy - ry, rx * 2, ry * 2))    return surfBG = make_gradient(W, H, (81034), (341654))MOON_X, MOON_Y, MOON_R = W - 26020084MOON_GLOW = make_glow(MOON_R * 3, (255240190), 1202.0)HALO = make_glow(140, (170200255), 702.4)SPARK = make_spark(28)stars = [{    "x": random.uniform(0, W),    "y": random.uniform(0, H),    "r": random.choice((1112223)),    "phase": random.uniform(0, TAU),    "speed": random.uniform(0.62.2),for _ in range(170)]clouds = [    {"surf": make_cloud(460170), "x": -80.0"y"430.0"v"14.0},    {"surf": make_cloud(360140), "x"560.0"y"520.0"v": -10.0},    {"surf": make_cloud(320130), "x"250.0"y"330.0"v"20.0},]CH = 480                                        # 嫦娥绘制画布尺寸change_layer = pygame.Surface((CH, CH), pygame.SRCALPHA)# ───────── 嫦娥绘制 ─────────def draw_change(layer, t, scale):    """在 layer 中心绘制嫦娥,scale 为整体缩放"""    cx = cy = CH / 2    def P(x, y):        return (cx + x * scale, cy + y * scale)    def Pi(x, y):        px, py = P(x, y)        return (int(px), int(py))    skin = (255227203)    hair = (342848)    robe = (238244255)    belt = (152182238)    # 背后柔光    layer.blit(HALO, (int(cx - HALO.get_width() / 2),                      int(cy - 10 - HALO.get_height() / 2)))    # ── 飘带(两侧长丝带,正弦摆动)──    for side in (-11):        def ribbon(offset):            pts = []            for i in range(28):                f = i / 27                x = side * 168 * f                y = (-12 + 48 * f                     + math.sin(t * 2.1 + f * 5.5 + side * 1.6) * 26 * f                     + offset)                pts.append(Pi(x, y))            return pts        up, dn = ribbon(-7), ribbon(7)        pygame.draw.polygon(layer, (206226255160), up + dn[::-1])        pygame.draw.lines(layer, (255255255190), False, ribbon(0),                          max(1int(1.5 * scale)))    # ── 裙摆(底部正弦飘动)──    N = 22    left, right = [], []    for i in range(N):        f = i / (N - 1)        y = 6 + 86 * f        hw = 12 + 44 * (f ** 1.35)        wob = math.sin(t * 3.0 - f * 4.2) * 12 * f        left.append(Pi(-hw + wob * 0.7, y))        right.append(Pi(hw + wob, y))    pygame.draw.polygon(layer, (230239255), left + right[::-1])    pygame.draw.lines(layer, (255255255), False, left, max(1int(1.3 * scale)))    pygame.draw.lines(layer, (255255255), False, right, max(1int(1.3 * scale)))    # ── 上身 ──    pygame.draw.polygon(layer, robe, [        Pi(-118), Pi(-14, -30), Pi(-9, -48),        Pi(9, -48), Pi(14, -30), Pi(118)    ])    # 腰带    pygame.draw.polygon(layer, belt, [Pi(-122), Pi(122), Pi(1011), Pi(-1011)])    # ── 手臂(上扬姿态)──    aw = max(2int(4 * scale))    pygame.draw.line(layer, skin, Pi(-12, -42), Pi(-34, -70), aw)    pygame.draw.line(layer, skin, Pi(-34, -70), Pi(-48, -98), max(2, aw - 1))    pygame.draw.line(layer, skin, Pi(12, -44), Pi(32, -74), aw)    pygame.draw.line(layer, skin, Pi(32, -74), Pi(46, -104), max(2, aw - 1))    # 水袖    pygame.draw.polygon(layer, (215232255),                        [Pi(-48, -98), Pi(-62, -112), Pi(-52, -84)])    pygame.draw.polygon(layer, (215232255),                        [Pi(46, -104), Pi(62, -118), Pi(50, -90)])    # ── 脖子 ──    pygame.draw.line(layer, skin, Pi(0, -46), Pi(0, -56), max(2int(5 * scale)))    # ── 后发 ──    pygame.draw.circle(layer, hair, Pi(0, -72), max(2int(16 * scale)))    pygame.draw.line(layer, hair, Pi(-13, -66), Pi(-18, -40), max(2int(5 * scale)))    pygame.draw.line(layer, hair, Pi(13, -66), Pi(18, -40), max(2int(5 * scale)))    # ── 脸 ──    pygame.draw.circle(layer, skin, Pi(0, -70), max(2int(13 * scale)))    # ── 发髻 + 发簪 ──    pygame.draw.circle(layer, hair, Pi(0, -87), max(2int(8 * scale)))    pygame.draw.circle(layer, hair, Pi(-9, -83), max(2int(5 * scale)))    pygame.draw.circle(layer, hair, Pi(9, -83), max(2int(5 * scale)))    pygame.draw.circle(layer, (255216120), Pi(11, -89), max(1int(3 * scale)))    # ── 眼睛 ──    if scale > 0.55:        pygame.draw.circle(layer, (584462), Pi(-5, -70), max(1int(1.6 * scale)))        pygame.draw.circle(layer, (584462), Pi(5, -70), max(1int(1.6 * scale)))# ───────── 主循环 ─────────def main():    progress = 0.0    elapsed = 0.0    spark_timer = 0.0    particles = []    running = True    p0 = (-180.0, H + 150.0)          # 起点(画面外左下)    p1 = (W * 0.20, H * 0.70)         # 控制点    p2 = (MOON_X - 150.0, MOON_Y + 90.0)   # 终点(月亮左下)    while running:        dt = min(clock.tick(60) / 1000.00.05)        elapsed += dt        for event in pygame.event.get():            if event.type == pygame.QUIT:                running = False            elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:                running = False        # 背景        screen.blit(BG, (00))        # 星星闪烁        for s in stars:            b = 0.5 + 0.5 * math.sin(elapsed * s["speed"] + s["phase"])            v = int(120 + 135 * b)            pygame.draw.circle(screen, (v, v, min(255, v + 25)),                               (int(s["x"]), int(s["y"])), s["r"])        # 月亮 + 光晕 + 环形山        screen.blit(MOON_GLOW, (MOON_X - MOON_GLOW.get_width() // 2,                                MOON_Y - MOON_GLOW.get_height() // 2))        pygame.draw.circle(screen, (255249222), (MOON_X, MOON_Y), MOON_R)        for dx, dy, r in ((-26, -2013), (20, -329), (102416),                          (-34268), (40106)):            pygame.draw.circle(screen, (240232198), (MOON_X + dx, MOON_Y + dy), r)        # 云        for c in clouds:            c["x"] += c["v"] * dt            cw = c["surf"].get_width()            if c["v"] > 0 and c["x"] > W:                c["x"] = -cw            elif c["v"] < 0 and c["x"] + cw < 0:                c["x"] = W            screen.blit(c["surf"], (int(c["x"]), int(c["y"])))        # 嫦娥位置:二次贝塞尔插值        progress += dt * 0.12        if progress > 1.0:            progress = 0.0        u = 1 - progress        cxp = u * u * p0[0] + 2 * u * progress * p1[0] + progress * progress * p2[0]        cyp = u * u * p0[1] + 2 * u * progress * p1[1] + progress * progress * p2[1]        scale = lerp(1.150.62, progress)        change_layer.fill((0000))        draw_change(change_layer, elapsed, scale)        screen.blit(change_layer, (int(cxp - CH / 2), int(cyp - CH / 2)))        # 跟随的金色粒子        spark_timer += dt        while spark_timer > 0.03:            spark_timer -= 0.03            particles.append({                "x": cxp + random.uniform(-4040),                "y": cyp + random.uniform(-4040),                "vx": random.uniform(-2525),                "vy": random.uniform(-55, -15),                "age"0.0,                "life": random.uniform(0.71.6),            })        alive = []        for p in particles:            p["age"] += dt            if p["age"] >= p["life"]:                continue            p["x"] += p["vx"] * dt            p["y"] += p["vy"] * dt            p["vy"] += 10 * dt            a = 1 - p["age"] / p["life"]            SPARK.set_alpha(int(210 * a))            screen.blit(SPARK, (int(p["x"] - 14), int(p["y"] - 14)))            alive.append(p)        particles = alive        # 文字        title = FONT_TITLE.render("嫦 娥 奔 月"True, (255240205))        screen.blit(title, (5242))        tip = FONT_TIP.render("但愿人长久,千里共婵娟        ESC 退出",                              True, (160172214))        screen.blit(tip, (5496))        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  图像处理  机器学习数据库

相关学习资料