PK creative Spring Festival, I am participating in the “Spring Festival creative submission contest”, please see: Spring Festival creative submission Contest

Run a screenshot

Operation effect:





What? You said you couldn’t see the fireworks? I’ll do it in a different color. Please click on it.



The implementation process

The preparatory work

Use languages and frameworks: Python, PyGame. Pygame installation:

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

The basics you need to know

First of all, PyGame renders synchronously, so too many points on the same screen can cause stuttering. Second, PyGame’s code logic is to periodically render a series of screens to produce a continuous animation.

Framework basics you need to know:

  • Initialization process
import pygame
pygame.init()
pygame.mixer.init()
pygame.font.init()
Copy the code
  • To get the font
myfont = pygame.font.SysFont('simHei'.30)
textsurface = myfont.render(a[i], False, random_color(150.255))
screen.blit(textsurface, (80.30))
Copy the code
  • circle
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)
Copy the code
  • Loading background music
screen = pygame.display.set_mode(bg_size)
pygame.display.set_caption("Happy New Year")
bg = pygame.image.load(bg_img)
pygame.mixer.music.load('D:\ CloudMusic\ Hour Girl - Xiaguang - End song of "Fairy Century".mp3')
Copy the code

The core code

Basic frame

First, you need to implement a basic event loop for the shelf, as follows:

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("Happy New Year")
    pygame.mixer.music.load('D:\ CloudMusic\ Hour Girl - Xiaguang - End song of "Fairy Century".mp3')
    font_values = ['Happy New Year']

    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()
Copy the code

The process of snow

Now, to implement the snow process, first consider defining a set of initial snow points

def init_xue(bg_size) :
    snow_list = []
    for i in range(200):
        x_site = random.randrange(0, bg_size[0])  # snowflake center position
        y_site = random.randrange(0, bg_size[1])  # snowflake center position
        X_shift = random.randint(-1.1)  # x offset
        radius = random.randint(4.6)  # radius and y cycle drop
        xxxxx = random_color(150.255)
        snow_list.append([x_site, y_site, X_shift, radius, 255.255.255])
    return snow_list
Copy the code

Then implement the process of rendering the snow

def draw_xue(snow_list: [], screen, bg_size: [], grand_has: set, grand_list: []) :
    # Snowflake list loop
    Snow in the sky
    for i in range(len(snow_list)):
        # Draw snowflakes, color, position, size
        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)
        # Move snowflake position (next loop works)
        snow_list[i][0] += snow_list[i][2]
        snow_list[i][1] += snow_list[i][3]
        If snow falls off the screen, reset the position
        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]])
Copy the code

Integrated into the shelf above, the effect is as follows:



However, the current snow has no texture, you can consider piling some snow on the bottom, just need to make a special judgment when the snow falls to the ground.

The process of snow falling to the ground and piling up

In the previous snow procedure code, we maintained an array of Grand_list to maintain the effect of the snow pile

min_height = 100000
Snow on the ground
for i in range(len(grand_list)):
    if grand_list[i][0] < 375:
        min_height = min(min_height, grand_list[i][1])
Copy the code

Then enter the maintenance program:

draw_xue(snow_list, screen, bg_size, grand_has, grand_list)
Copy the code

Finally, draw the snow

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)
Copy the code



The renderings are shown above.

The process of realizing fireworks

First of all, define the fireworks category:

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
Copy the code

Then, we need to plot the point of ascent before the firework is released, which is similar to the initialization of snow.

def init_yanhua(bg_size) :
    yanhua_list = []
    for i in range(5):
        x_site = random.randrange(0, WIN_W)  # snowflake center position
        y_site = WIN_H  # snowflake center position
        X_shift = 0  # x offset
        radius = random.randint(6.10)  # radius and y-cycle rise and fall
        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
Copy the code

And then I’m going to draw the ascent

def draw_yanhua(yanhua_list: [], screen, bg_size: []) :
    global fk_list
    for i in range(len(yanhua_list)):
        # Draw snowflakes, color, position, size
        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 fireworks
            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])
Copy the code

The renderings are as follows:



Circled are the fireworks of the ascent.

And finally, the bloom part, which is actually maintained in the code for the ascent process, if you go beyond a certain random height, it will generate a firework, but it’s not rendered, so now we add the render.

        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
Copy the code

The end result is just like the top effect.

The complete code

By combining the above processes, the result is as follows, which interested friends can optimize according to their own needs.

import pygame
import random
import math

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

WIN_W = 2200
WIN_H = 1300

t1 = 0.18  # Time flow rate
show_n = 0
show_frequency = 0.0015  # Fireworks burst frequency, the higher the value, the higher the frequency


color_list = [
    [255.0.0]
]

yanhua_map = {}
fk_list = []


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 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)  # snowflake center position
        y_site = WIN_H  # snowflake center position
        X_shift = 0  # x offset
        radius = random.randint(6.10)  # radius and y-cycle rise and fall
        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])  # snowflake center position
        y_site = random.randrange(0, bg_size[1])  # snowflake center position
        X_shift = random.randint(-1.1)  # x offset
        radius = random.randint(4.6)  # radius and y cycle drop
        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: []) :
    # Snowflake list loop
    Snow in the sky
    for i in range(len(snow_list)):
        # Draw snowflakes, color, position, size
        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)
        # Move snowflake position (next loop works)
        snow_list[i][0] += snow_list[i][2]
        snow_list[i][1] += snow_list[i][3]
        If snow falls off the screen, reset the position
        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)):
        # Draw snowflakes, color, position, size
        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)
        # Move snowflake position (next loop works)
        yanhua_list[i][0] += yanhua_list[i][2]
        yanhua_list[i][1] -= yanhua_list[i][3]
        If snow falls off the screen, reset the position
        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 fireworks
            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)
        textsurface = 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("Happy New Year")
    # bg = pygame.image.load(bg_img)
    pygame.mixer.music.load('D:\ CloudMusic\ Hour Girl - Xiaguang - End song of "Fairy Century".mp3')
    grand_list = []
    font_values = ['Happy New Year']

    grand_has = set()

    clock = pygame.time.Clock()
    yanhua_list = init_yanhua(bg_size)
    snow_list = init_xue(bg_size)
    # Game main loop
    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))
        draw_yanhua(yanhua_list, screen, bg_size)
        if len(fk_list) ! =0:
            print(len(fk_list))
        # # Fireworks
        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
        Snow on the ground
        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()

Copy the code