开发者

Python Pygame制作雪夜烟花景

目录
  • 运行截图
  • 实现过程
  • 核心代码
    • 基础架子
    • 下雪的过程
    • 雪落到地上堆起来的过程
    • 实现烟花的过程
  • 完整代码

    运行截图

    运行效果:

    Python Pygame制作雪夜烟花景

    什么?你说你看不清烟花?那我换一种颜色,请点开看。

    Python Pygame制作雪夜烟花景

    实现过程

    准备工作

    使用语言和框架:python、pygame。

    安装pygame:

    pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ --trusted-host pypi.tuna.tsinghua.edu.cn pygame
    

    你需要知道的基础知识

    首先,pygame渲染是同步的,所以同屏渲染的点过多之后,就会造成卡顿的情况。

    其次,pygame的代码逻辑是,周期性渲染一系列的屏,从而产生连续的动画。

    你需要掌握的框架基础知识:

    初始化过程

    import pygame
    pygame.init()
    pygame.mixer.init()
    pygame.font.init()
    

    获取字体

    myfont = pygame.font.SysFont('simHei', 30)
    textsurface = myfont.render(a[i], False, random_color(150, 255))
    screen.blit(textsurface, (80, 30))
    

    画圈

    pygame.draw.circle(screen, (snow_list[i][4], snow_list[i][5], snow_list[i][6]), snow_list[i][:2],
                               snow_list[i][3] - 3)
    

    加载背景音乐

    screen = pygame.display.set_mode(bg_size)
    pygame.display.set_caption("新年快乐")
    bg = pygame.image.load(bg_img)
    pygame.mixer.music.load('D:\\CloudMusic\\小时姑娘 - 霞光-《精灵世纪》片尾曲.mp3')
    

    核心代码

    基础架子

    首先,需要实现一个基础的事件循环的架子,如下:

    def main():
      global show_n
      global fk_list
      bg_size = (WIN_W, WIN_H)
      screen = pygame.display.set_mode(bg_size)
      pygame.display.set_caption("新年快乐")
      pygame.mixer.music.load('D:\\CloudMusic\\小时姑娘 - 霞光-《精灵世纪》片尾曲.mp3')
      font_values = ['新年快乐']
    
      grand_has = set()
      clock = pygame.time.Clock()
    
      while True:
        if not pygame.mixer.music.get_busy():
          pygame.mixer.music.play()
        for event in pygame.event.get():
          if event.type == pygame.QUIT:
            exit()
        screen.fill((0, 0, 0))
        ... ...
        pygame.display.update()
        time_passed = clock.tick(50)
    
    
    if __name__ == '__main__':
      main()

    下雪的过程

    现在,需要实现下雪的过程,首先,考虑定义定义一堆初始化的下雪点

    def init_xue(bg_size):
        snow_list = []
        for i in range(200):
            x_site = random.randrange(0, bg_size[0])  # 雪花圆心位置
            y_site = random.randrange(0, bg_size[1])  # 雪花圆心位置
            X_shift = random.randint(-1, 1)  # x 轴偏移量
            radius = random.randint(4, 6)  # 半径和 y 周下降量
            xxxxx = random_color(150, 255)
            snow_list.append([x_site, y_site, X_shift, radius, 255, 255, 255])
        return snow_list
    

    然后实现渲染雪的过程

    def draw_xue(snow_list: [], screen, bg_size: [], grand_has: set, grand_list: []):
        # 雪花列表循环
        # todo 空中的雪
        for i in range(len(snow_list)):
            # 绘制雪花,颜色、位置、大小
            pygame.draw.circle(screen, (snow_list[i][4], snow_list[i][5], snow_list[i][6]), snow_list[i][:2],
                               snow_list[i][3] - 3)
            # 移动雪花位置(下一次循环起效)
            snow_list[i][0] += snow_list[i][2]
            snow_list[i][1] += snow_list[i][3]
            # 如果雪花落出屏幕,重设位置
            if snow_list[i][1] > bg_size[1]:
                # tmp = []
                snow_list[i][1] = random.randrange(-50, -10)
                snow_list[i][0] = random.randrange(0, bg_size[0])
                x = snow_list[i][0]
                y = bg_size[1]
                while (grand_has.__contains__(x * 10000 + y)):
                    y = y - snow_list[i][3]
                grand_has.add(x * 10000 + y)
                grand_list.append(
                    [x, y, snow_list[i][2], snow_list[i][3], snow_list[i][4], snow_list[i][5],
                     snow_list[i][6]])
    

    集成到上面的架子中,效果如下:

    Python Pygame制作雪夜烟花景

    不过目前的下雪没有质感,可以考虑在底部堆一些雪,只需要在雪落到地上做特判即可。

    雪落到地上堆起来的过程

    在前面的下雪过程的代码中,我们维护了一个Grand_list的数组,目的就是维护堆雪的效果

    min_height = 100000
    # todo 地上的积雪
    for i in range(len(grand_list)):
        if grand_list[i][0] < 375:
            min_height = min(min_height, grand_list[i][1])
    

    然后进入维护程序:

    draw_xue(snow_list, screen, bg_size, grand_has, grand_list)
    

    最后再将雪画出来

    for i in range(len(grand_list)):
        pygame.draw.circle(screen, (grand_list[i][4], grand_list[i][5], grand_list[i][6]), grand_list[i][:2],
                           grand_list[i][3] - 3)
    

    Python Pygame制作雪夜烟花景

    效果图如上。

    实现烟花的过程

    首先定义出烟花类:

    class Fireworks():
      is_show = False
      x, y = 0, 0
      vy = 0
      p_list = []
      color = [0, 0, 0]
      v = 0
    
      def __init__(self, x, y, vy, n=300, color=[0, 255, 0], v=10):
        self.x = x
        self.y = y
        self.vy = vy
        self.color = color
        self.v = v
        for i in range(n):
          self.p_list.append([random.random() * 2 * math.pi, 0, v * math.pow(random.random(), 1 / 3)])
    
      def run(self):
        global show_n
        for p in self.p_list:
          p[1] = p[1] + (random.random() * 0.6 + 0.7) * p[2]
          p[2] = p[2] * 0.97
          if p[2] < 1.2:
            self.color[0] *= 0.9999
            self.color[1] *= 0.9999
            self.color[2] *= 0.9999
          if max(self.color) < 10 or self.y > WIN_H + p[1]:
            show_n -= 1
            self.is_show = False
            break
        self.vy += 10 * t1
        self.y += self.vy * t1

    然后,我们需要画出烟花释放前上升的过程点,这部分与下雪的初始化差不多。

    def init_yanhua(bg_size):
        yanhua_list = []
        for i in range(5):
            x_site = random.randrange(0, WIN_W)  # 雪花圆心位置
            y_site = WIN_H  # 雪花圆心位置
            X_shift = 0  # x 轴偏移量
            radius = random.randint(6, 10)  # 半径和 y 周上升降量
            xxxxx = random_color(150, 255)
            red = xxxxx[0]
            green = xxxxx[1]
            blue = xxxxx[2]
            yanhua_list.append([x_site, y_site, X_shift, radius, red, green, blue])
        return yanhua_list
    

    然后是画上升过程

    def draw_yanhua(yanhua_list: [], screen, bg_size: []):
      global fk_list
      for i in range(len(yanhua_list)):
        # 绘制雪花,颜色、位置、大小
        pygame.draw.circle(screen, (yanhua_list[i][4], yanhua_list[i][5], yanhua_list[i][6]), yanhua_list[i][:2],
                 yanhua_list[i][3] - 3)
       
        yanhua_list[i][0] += yanhua_list[i][2]
        yanhua_list[i][1] -= yanhua_list[i][3]
    
        if yanhua_list[i][1] <= 0:
          # tmp = []
          yanhua_list[i][1] = WIN_H
          yanhua_list[i][0] = random.randrange(0, bg_size[0])
        if yanhua_list[i][1] <= random.randint(200, 400):
          # todo 放烟花
          fk = Fireworks(yanhua_list[i][0], yanhua_list[i][1], -20, n=300, color=red_random(1, 150), v=10)
          fk_list.append(fk)
          yanhua_list[i][1] = WIN_H
          yanhua_list[i][0] = random.randrange(0, bg_size[0])

    效果图如下:

    Python Pygame制作雪夜烟花景

    圈出来的就是上升过程的烟花。

    最后就是绽放部分,其实在上升过程的代码中有维护,如果超过某个随机高度,就会生成一个烟花,只是没有渲染,现在我们把渲染加上。

            for fk in fk_list:
                fk.run()
                for p in fk.p_list:
                    x, y = fk.x + p[1] * math.cos(p[0]), fk.y + p[1] * math.sin(p[0])
                    if random.random() < 0.055:
                        screen.set_at((int(x), int(y)), (255, 255, 255))
                    else:
                        screen.set_at((int(x), int(y)), (int(fk.color[0]), int(fk.color[1]), int(fk.color[2])))
            tmp = []
            for fk in fk_list:
                for p in fk.p_list:
                    x, y = fk.x + p[1] * math.cos(p[0]), fk.y + p[1] * math.sin(p[0])
                    if y < WIN_H - 1000:
                        tmp.append(fk)
                        break
            fk_list = tmp
    

    最终的运行效果就如最顶上的效果一样。

    完整代码

    将上述过程进行组合,结果如下,感兴趣的朋友可以按自己的需求进行优化。

    import pygame
    import random
    import math
    
    pygame.init()
    pygame.mixer.init()
    pygame.font.init()
    
    WIN_W = 2200
    WIN_H = 1300
    
    t1 = 0.18 # 时间流速
    show_n = 0
    show_frequency = 0.0015 # 烟花绽放频率,数值越大频率越高
    
    
    color_list = [
      [255, 0, 0]
    ]
    
    yanhua_map = {}
    fk_list = []
    
    
    class Fireworks():
      is_show = False
      x, y = 0, 0
      vy = 0
      p_list = []
      color = [0, 0wQechyw, 0]
      v = 0
    
      def __init__(self, x, y, vy, n=300, color=[0, 255, 0], v=10):
        self.x = x
        self.y = y
        self.vy = vy
        self.color = color
        self.v = v
        for i in range(n):
          self.p_list.append([random.random() * 2 * math.pi, 0, v * math.pow(random.random(), 1 / 3)])
    
      def run(self):
        global show_n
        for p in self.p_list:
          p[1] = p[1] + (random.random() * 0.6 + 0.7) * p[2]
          p[2] = p[2] * 0.97
          if p[2] < 1.2:
            self.color[0] *= 0.9999
            self.color[1] *= 0.9999
            self.color[2] *= 0.9999
          if max(self.color) < 10 or self.y > WIN_H + p[1]:
            show_n -= 1
            self.is_show = False
            break
        self.vy += 10 * t1
        self.y += self.vy * t1
    
    
    def random_color(l, r):
      return [random.randint(l, r), random.randint(l, r), random.randint(l, r)]
    
    
    def red_random(l, r):
      return [255, random.randint(l, r), random.randint(l, r)]
    
    
    def init_yanhua(bg_size):
      yanhua_list = []
      for i in range(5):
        x_site = random.randrange(0, WIN_W) # 雪花圆心位置
        y_site = WIN_H # 雪花圆心位置
        X_shift = 0 # x 轴偏移量
        radius = random.randint(6, 10) # 半径和 y 周上升降量
        xxxxx = random_color(150, 255)
        red = xxxxx[0]
        green = xxxxx[1]
        blue = xxxxx[2]
        yanhua_list.append([x_site, y_site, X_shift, radius, red, green, blue])
      return yanhua_list
    
    
    def init_xue(bg_size):
      snow_list = []
      for i in range(200):
        x_site = random.randrange(0, bg_size[0]) # 雪花圆心位置
        y_site = random.randrange(0, bg_size[1]) # 雪花圆心位置
        X_shift = random.randint(-1, 1) # x 轴偏移量
        radius = random.randint(4, 6) # 半径和 y 周下降量
        xxxxx = random_color(150, 255)
        # red = xxxxx[0]
        # green = xxxxx[1]
        # blue = xxxxx[2]
        snow_list.append([x_site, y_site, X_shift, radius, 255, 255, 255])
      return snow_list
    
    
    def draw_xue(snow_list: [], screen, bg_size: [], grand_has: set, grand_list: []):
      # 雪花列表循环
      # todo 空中的雪
      for i in range(len(snow_list)):
        # 绘制雪花,颜色、位置、大小
        pygame.draw.circle(screen, (snow_list[i][4], snow_list[i][5], snow_list[i][6]), snow_list[i][:2],
                 snow_list[i][3] - 3)
        # 移动雪花位置(下一次循环起效)
        snow_list[i][0] += snow_list[i][2]
        wQechywsnow_list[i][1] += snow_list[i][3]
        # 如果雪花落出屏幕,重设位置
        if snow_list[i][1] > bg_size[1]:
          # tmp = []
          snow_list[i][1] = random.randrange(-50, -10)
          snow_list[i][0] = random.randrange(0, bg_size[0])
          x = snow_list[i][0]
          y = bg_size[1]
          while (grand_has.__contains__(x * 10000 + y)):
            y = y - snow_list[i][3]
          grand_has.add(x * 10000 + y)
          grand_list.append(
            [x, y, snow_list[i][2], snow_list[i][3], snow_list[i][4], snow_list[i][5],
            snow_list[i][6]])
    
    def draw_yanhua(yanhua_list: [], screen, bg_size: []):
      global fk_list
      for i in range(len(yanhua_list)):
        # 绘制雪花,颜色、位置、大小
        pygame.draw.circle(screen, (yanhua_list[i][4], yanhua_list[i][5], yanhua_list[i][6]), yanhua_list[i][:2],
                 yanhua_list[i][3] - 3)
        # 移动雪花位置(下一次循环起效)
        yanhua_list[i][0] += yanhua_list[i][2]
        yanhua_list[i][1] -= yanhua_list[i][3]
        # 如果雪花落出屏幕,重设位置
        if yanhua_list[i][1] <= 0:
          # tmp = []
          yanhua_list[i][1] = WIN_H
          yanhua_list[i][0] = random.randrange(0, bg_size[0])
        if yanhua_list[i][1] <= random.randint(200, 400):
          # todo 放烟花
          fk = Fireworks(yanhua_list[i][0], yanhua_list[i][1], -20, n=300, color=red_random(1, 150), v=10)
          fk_list.append(fk)
          yanhua_list[i][1] = WIN_H
          yanhua_list[i][0] = random.randrange(0, bg_size[0])
    
    
    def show_shi(a: list, n, screen):
      i = 2 * n - 1
      j = 2 * n
      if i >= len(a):
        i = len(a) - 2
        j = len(a) - 1
      if i >= 0:
        myfont = pygame.font.SysFont('simHei', 30)
        textsurface = myfont.render(a[i], False, random_color(150, 255))
        screen.blit(textsurface, (WIN_W / 2, 30))
      if j >= 0:
        myfont = pygame.font.SysFont('simHei', 100)
        textsu编程客栈rface = myfont.render(a[j], False, red_random(1, 1))
        screen.blit(textsurface, (WIN_W / 2 - 200, 50))
    
    
    def main():
      global show_n
      global fk_list
      bg_size = (WIN_W, WIN_H)
      screen = pygame.display.set_mode(bg_size)
      # bg_img = "./1.png"
      pygame.display.set_caption("新年快乐")
      # www.cppcns.combg = pygame.image.load(bg_img)
      pygame.mixer.music.load('D:\\CloudMusic\\小时姑娘 - 霞光-《精灵世纪》片尾曲.mp3')
      grand_list = []
      font_values = ['新年快乐']
    
      grand_has = set()
    
      clock = pygame.time.Clock()
      yanhua_list = init_yanhua(bg_size)
      snow_list = init_xue(bg_size)
      # 游戏主循环
      while True:
        if not pygame.mixer.music.get_busy():
          pygame.mixer.music.play()
        for event in pygame.event.get():
          if event.type == pwww.cppcns.comygame.QUIT:
            exit()
        screen.fill((0, 0, 0))
        draw_yanhua(yanhua_list, screen, bg_size)
        if len(fk_list) != 0:
          print(len(fk_list))
        # # 放烟花
        show_shi(font_values, 0, screen)
        for fk in fk_list:
          fk.run()
          for p in fk.p_list:
            x, y = fk.x + p[1] * math.cos(p[0]), fk.y + p[1] * math.sin(p[0])
            if random.random() < 0.055:
              screen.set_at((int(x), int(y)), (255, 255, 255))
            else:
              screen.set_at((int(x), int(y)), (int(fk.color[0]), int(fk.color[1]), int(fk.color[2])))
        tmp = []
        for fk in fk_list:
          for p in fk.p_list:
            x, y = fk.x + p[1] * math.cos(p[0]), fk.y + p[1] * math.sin(p[0])
            if y < WIN_H - 1000:
              tmp.append(fk)
              break
        fk_list = tmp
        min_height = 100000
        # todo 地上的积雪
        for i in range(len(grand_list)):
          if grand_list[i][0] < 375:
            min_height = min(min_height, grand_list[i][1])
    
        draw_xue(snow_list, screen, bg_size, grand_has, grand_list)
        for i in range(len(grand_list)):
          pygame.draw.circle(screen, (grand_list[i][4], grand_list[i][5], grand_list[i][6]), grand_list[i][:2],
                   grand_list[i][3] - 3)
        pygame.display.update()
        time_passed = clock.tick(50)
    
    
    if __name__ == '__main__':
      main()

    以上就是Python Pygame制作雪夜烟花景的详细内容,更多关于Python Pygame的资料请关注我们其它相关文章!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜