Python Pygame制作雪夜烟花景
作者:炒鸡辣鸡123 发布时间:2023-10-21 08:57:07
标签: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]])
集成到上面的架子中,效果如下:
不过目前的下雪没有质感,可以考虑在底部堆一些雪,只需要在雪落到地上做特判即可。
雪落到地上堆起来的过程
在前面的下雪过程的代码中,我们维护了一个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)
效果图如上。
实现烟花的过程
首先定义出烟花类:
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])
效果图如下:
圈出来的就是上升过程的烟花。
最后就是绽放部分,其实在上升过程的代码中有维护,如果超过某个随机高度,就会生成一个烟花,只是没有渲染,现在我们把渲染加上。
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, 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) # 雪花圆心位置
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]
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]])
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)
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("新年快乐")
# bg = 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 == pygame.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()
来源:https://blog.csdn.net/xielinrui123/article/details/122701390


猜你喜欢
- 一、程序导出word文档的方法将web/html内容导出为world文档,再java中有很多解决方案,比如使用Jacob、Apache PO
- while循环是在Python中的循环结构之一。 while循环继续,直到表达式变为假。表达的是一个逻辑表达式,必须返回一个true或fal
- 前言本文主要给大家介绍了关于Python3用SMTP协议发送电子邮件的相关内容,在介绍如何使用python程序向指定邮箱发送邮件之前,我们需
- 前言本文使用 cpu 版本的 tensorflow 2.4 ,在 shakespeare 数据的基础上使用 Skip-Gram 算法训练词嵌
- 目录现象根因分析getLastPacketReceivedTimeMs()方法调用时机解决方案现象应用升级MySQL驱动8.0后,在并发量较
- 字符串就是一个话题中心。给字符串编号在很多很多情况下,我们都要对字符串中的每个字符进行操作(具体看后面的内容),要准确进行操作,必须做的一个
- 一、Tornado简介Tornado 是 FriendFeed 的 Web 服务器及其常用工具的开源版本。Tornado 和现在的主流 We
- 如图输入如下命令python manage.py startapp apitest添加应用到 autotest项目项目下在settings.
- 一,用临时表作为数组 create function f_split(@c varchar(2000),@split varchar(2))
- 在用ThinkPHP做tags标签的时候,出现了一个问题,就是能获取到参数,但是查不出相应的结果。查看数据库发现数据是存在的。问题出在哪了呢
- Python的json模块提供了一种很简单的方式来编码和解码JSON数据。 其中两个主要的函数是 json.dumps() 和 json.l
- 你有没有觉得你的CSS样式表文件过于臃肿?其实如果你注意并培养一些比较好的CSS书写习惯,我想你的CSS样式表过于”肥胖”的问题会得到很好的
- 前言最近有人对自动上传与发布很感兴趣,都私下找我说了好几次了。今天,必须把他安排,必须实力宠粉。“本篇依次介绍目前主流的
- 我们通常说的双机热备是指两台机器都在运行,但并不是两台机器都同时在提供服务。当提供服务的一台出现故障的时候,另外一台会马上自动接管并且提供服
- 把函数作为参数的用法比较直观:def func(a, b): return a + bdef test(f, a, b): print f
- 代码如下:'============================== '格式化HTML,SDCMS加强版 '==
- 起源就在今年9月份,我负责的部门平台项目发布了一个新版本,该版本同时上线了一个新功能,简单说有点类似定时任务。头一天一切正常,但第二天出现了
- 大家好,常用探索性数据分析方法很多,比如常用的 Pandas DataFrame 方法有 .head()、.tail()、.info()、.
- 如下所示:import jsonresult = response.read()result.decode('utf-8')
- 如何在聊天室实现趣味答题并计分功能?这个创意确实很好,我们可用在聊天室框架中加入一隐含帧(5分钟刷新一次)的做法来实现这一功能。questi