SoFunction
Updated on 2024-11-17

Python Pygame to create a snowy night fireworks scene

Screenshots

Running effects:

What? You say you can't see the fireworks? Then I'll change the color. Please click on it.

implementation process

preliminary

Languages and frameworks used: python, pygame.

Install pygame.

pip install -i /simple/ --trusted-host  pygame

The basics you need to know

First of all, pygame rendering is synchronized, so after too many points are rendered on the same screen, it can cause lag.

Second, the logic of pygame's code is to periodically render a series of screens, which produces a continuous animation.

The framework basics you need to master:

initialization process

import pygame
()
()
()

Get Fonts

myfont = ('simHei', 30)
textsurface = (a[i], False, random_color(150, 255))
(textsurface, (80, 30))

draw a circle

(screen, (snow_list[i][4], snow_list[i][5], snow_list[i][6]), snow_list[i][:2],
                           snow_list[i][3] - 3)

Loading background music

screen = .set_mode(bg_size)
.set_caption("Happy New Year.")
bg = (bg_img)
('D:\\\CloudMusic\\\\\Hourly Girl - Kasumi - "Elf Century" End Credits.mp3')

core code

base elevator

First, a basic event loop shelf needs to be implemented as follows:

def main():
    global show_n
    global fk_list
    bg_size = (WIN_W, WIN_H)
    screen = .set_mode(bg_size)
    .set_caption("Happy New Year.")
    ('D:\\\CloudMusic\\\\\Hourly Girl - Kasumi - "Elf Century" End Credits.mp3')
    font_values = ['Happy New Year']

    grand_has = set()
    clock = ()

    while True:
        if not .get_busy():
            ()
        for event in ():
            if  == :
                exit()
        ((0, 0, 0))
        ... ...
        ()
        time_passed = (50)


if __name__ == '__main__':
    main()

The process of snowing

Now, the snowing process needs to be implemented, first, consider defining defining a bunch of initialized snowing points

def init_xue(bg_size):
    snow_list = []
    for i in range(200):
        x_site = (0, bg_size[0])  # Snowflake center position
        y_site = (0, bg_size[1])  # Snowflake center position
        X_shift = (-1, 1)  # x-axis offset
        radius = (4, 6)  # Radius and y-week decline
        xxxxx = random_color(150, 255)
        snow_list.append([x_site, y_site, X_shift, radius, 255, 255, 255])
    return snow_list

Then realize the process of rendering snow

def draw_xue(snow_list: [], screen, bg_size: [], grand_has: set, grand_list: []):
    # Snowflake list loop
    # todo Snow in the sky
    for i in range(len(snow_list)):
        # Drawing snowflakes, color, position, size
        (screen, (snow_list[i][4], snow_list[i][5], snow_list[i][6]), snow_list[i][:2],
                           snow_list[i][3] - 3)
        # Move the snowflake position (next cycle takes effect)
        snow_list[i][0] += snow_list[i][2]
        snow_list[i][1] += snow_list[i][3]
        # If the snowflake falls off the screen, reset the position
        if snow_list[i][1] > bg_size[1]:
            # tmp = []
            snow_list[i][1] = (-50, -10)
            snow_list[i][0] = (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]])

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

However, the current snowfall has no texture, so consider piling some snow on the bottom and just doing special judgments as it falls to the ground.

The process of snow falling to the ground and piling up

In the previous code for the snow process, we maintained an array of Grand_lists for the purpose of maintaining the snow pile effect

min_height = 100000
# todo 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])

Then enter the maintenance program:

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

And then finally the snow will be painted

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

The rendering is as above.

The process of realizing fireworks

First define the fireworks class:

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):
         = x
         = y
         = vy
         = color
         = v
        for i in range(n):
            self.p_list.append([() * 2 * , 0, v * ((), 1 / 3)])

    def run(self):
        global show_n
        for p in self.p_list:
            p[1] = p[1] + (() * 0.6 + 0.7) * p[2]
            p[2] = p[2] * 0.97
            if p[2] < 1.2:
                [0] *= 0.9999
                [1] *= 0.9999
                [2] *= 0.9999
            if max() < 10 or  > WIN_H + p[1]:
                show_n -= 1
                self.is_show = False
                break
         += 10 * t1
         +=  * t1

Then, we need to draw the process point where the firework rises before it is released, this part is similar to the initialization of the snow.

def init_yanhua(bg_size):
    yanhua_list = []
    for i in range(5):
        x_site = (0, WIN_W)  # Snowflake center position
        y_site = WIN_H  # Snowflake center position
        X_shift = 0  # x-axis offset
        radius = (6, 10)  # Radius and y-periodic 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

Then there's the drawing up process

def draw_yanhua(yanhua_list: [], screen, bg_size: []):
    global fk_list
    for i in range(len(yanhua_list)):
        # Drawing snowflakes, color, position, size
        (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] = (0, bg_size[0])
        if yanhua_list[i][1] <= (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] = (0, bg_size[0])

The rendering is as follows:

The circled ones are the fireworks of the rising process.

And finally the bloom part, there is actually maintenance in the code for the ascent process that generates a firework if a certain random height is exceeded, it's just not rendered, now let's add the rendering.

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

The final run will look like the effect at the very top.

Full Code

Combining the above processes, the results are as follows, and those interested can optimize them for their own needs.

import pygame
import random
import math

()
()
()

WIN_W = 2200
WIN_H = 1300

t1 = 0.18  # Time flow rate
show_n = 0
show_frequency = 0.0015  # Frequency of fireworks, 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):
         = x
         = y
         = vy
         = color
         = v
        for i in range(n):
            self.p_list.append([() * 2 * , 0, v * ((), 1 / 3)])

    def run(self):
        global show_n
        for p in self.p_list:
            p[1] = p[1] + (() * 0.6 + 0.7) * p[2]
            p[2] = p[2] * 0.97
            if p[2] < 1.2:
                [0] *= 0.9999
                [1] *= 0.9999
                [2] *= 0.9999
            if max() < 10 or  > WIN_H + p[1]:
                show_n -= 1
                self.is_show = False
                break
         += 10 * t1
         +=  * t1


def random_color(l, r):
    return [(l, r), (l, r), (l, r)]


def red_random(l, r):
    return [255, (l, r), (l, r)]


def init_yanhua(bg_size):
    yanhua_list = []
    for i in range(5):
        x_site = (0, WIN_W)  # Snowflake center position
        y_site = WIN_H  # Snowflake center position
        X_shift = 0  # x-axis offset
        radius = (6, 10)  # Radius and y-periodic 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 = (0, bg_size[0])  # Snowflake center position
        y_site = (0, bg_size[1])  # Snowflake center position
        X_shift = (-1, 1)  # x-axis offset
        radius = (4, 6)  # Radius and y-week decline
        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
    # todo Snow in the sky
    for i in range(len(snow_list)):
        # Drawing snowflakes, color, position, size
        (screen, (snow_list[i][4], snow_list[i][5], snow_list[i][6]), snow_list[i][:2],
                           snow_list[i][3] - 3)
        # Move the snowflake position (next cycle takes effect)
        snow_list[i][0] += snow_list[i][2]
        snow_list[i][1] += snow_list[i][3]
        # If the snowflake falls off the screen, reset the position
        if snow_list[i][1] > bg_size[1]:
            # tmp = []
            snow_list[i][1] = (-50, -10)
            snow_list[i][0] = (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)):
        # Drawing snowflakes, color, position, size
        (screen, (yanhua_list[i][4], yanhua_list[i][5], yanhua_list[i][6]), yanhua_list[i][:2],
                           yanhua_list[i][3] - 3)
        # Move the snowflake position (next cycle takes effect)
        yanhua_list[i][0] += yanhua_list[i][2]
        yanhua_list[i][1] -= yanhua_list[i][3]
        # If the snowflake falls off the screen, reset the position
        if yanhua_list[i][1] <= 0:
            # tmp = []
            yanhua_list[i][1] = WIN_H
            yanhua_list[i][0] = (0, bg_size[0])
        if yanhua_list[i][1] <= (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] = (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 = ('simHei', 30)
        textsurface = (a[i], False, random_color(150, 255))
        (textsurface, (WIN_W / 2, 30))
    if j >= 0:
        myfont = ('simHei', 100)
        textsurface = (a[j], False, red_random(1, 1))
        (textsurface, (WIN_W / 2 - 200, 50))


def main():
    global show_n
    global fk_list
    bg_size = (WIN_W, WIN_H)
    screen = .set_mode(bg_size)
    # bg_img = "./"
    .set_caption("Happy New Year.")
    # bg = (bg_img)
    ('D:\\\CloudMusic\\\\\Hourly Girl - Kasumi - "Elf Century" End Credits.mp3')
    grand_list = []
    font_values = ['Happy New Year']

    grand_has = set()

    clock = ()
    yanhua_list = init_yanhua(bg_size)
    snow_list = init_xue(bg_size)
    # The main game loop
    while True:
        if not .get_busy():
            ()
        for event in ():
            if  == :
                exit()
        ((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:
            ()
            for p in fk.p_list:
                x, y =  + p[1] * (p[0]),  + p[1] * (p[0])
                if () < 0.055:
                    screen.set_at((int(x), int(y)), (255, 255, 255))
                else:
                    screen.set_at((int(x), int(y)), (int([0]), int([1]), int([2])))
        tmp = []
        for fk in fk_list:
            for p in fk.p_list:
                x, y =  + p[1] * (p[0]),  + p[1] * (p[0])
                if y < WIN_H - 1000:
                    (fk)
                    break
        fk_list = tmp
        min_height = 100000
        # todo 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)):
            (screen, (grand_list[i][4], grand_list[i][5], grand_list[i][6]), grand_list[i][:2],
                               grand_list[i][3] - 3)
        ()
        time_passed = (50)


if __name__ == '__main__':
    main()

Above is the detailed content of Python Pygame to create a snowy night fireworks scene, more information about Python Pygame please pay attention to my other related articles!