看到很多小伙伴使用python实现了很多动态的效果,非常漂亮。
闲来无事,也参考做法,自己做了一幅雪落动图。过程中,遇到了一些问题,花了点时间搞定。
基础代码问了chatGPT,但是初始实现效果,不是很理想。
import pygame
import random
# 初始化Pygame
pygame.init()
# 设置窗口尺寸和标题
window_width = 800
window_height = 600
window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("雪花飘落")
# 定义雪花颜色为白色
WHITE = (255, 255, 255)
# 创建雪花列表
snowflakes = []
# 创建雪花对象
class Snowflake:
def __init__(self, x, y, size):
self.x = x
self.y = y
self.size = size
self.speed = random.randint(1, 8)
def fall(self):
self.y += self.speed
if self.y > window_height:
self.y = random.randint(-50, -10)
self.x = random.randint(0, window_width)
def draw(self):
pygame.draw.circle(window, WHITE, (self.x, self.y), self.size)
# 创建GIF帧的列表
# 主循环
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 清空窗口
window.fill((0, 0, 0))
# 生成雪花
# 控制生成雪花的数量,数量可以更改
if len(snowflakes) < 100:
x = random.randint(0, window_width)
y = random.randint(0, window_height)
# 定义雪花的大小,1-5之间随机,可以根据自己需求更改
size = random.randint(1, 5)
snowflake = Snowflake(x, y, size)
snowflakes.append(snowflake)
# 更新和绘制雪花
for snowflake in snowflakes:
snowflake.fall()
snowflake.draw()
# 刷新窗口
pygame.display.flip()
# 控制帧率
pygame.time.delay(10)
# 退出时关闭Pygame
pygame.quit()
呈现效果如下:
原始代码是黑色背景,肯定不是我们期望的样子,我们预期增加一张美丽的背景图片来润色。
更换雪景背景,首先要导入一个模块
from PIL import Image
根据背景图片修改窗口的大小。
window_width = 1280
window_height = 800
加载背景图片,图片把他放到了与代码文件相同的路径下。
# 加载背景图片
background_image= pygame.image.load("snow.jpg")
在窗口绘制背景图片,取代这一行代码:window.fill((0, 0, 0))
# 绘制背景图片
window.blit(background_image,(0,0))
更换背景后,效果呈现:
因为产生的动图,还没有定义格式,我们转变为GIF的动图。
先创建一个帧列表
# 创建GIF帧的列表
frames = []
获取当前帧的截图,并添加到列表
# 获取当前帧的截图并添加到帧列表
pygame_image = pygame.surfarray.array3d(pygame.display.get_surface())
pil_image = Image.fromarray(pygame_image)
pil_image = pil_image.rotate(-90,expand=True)
frames.append(pil_image.copy())
这里需要注意pil_image = pil_image.rotate(-90,expand=True)的应用,默认压缩后的GIF动图可以因为某些原因自动旋转90度。我们通过pil_image.rotate设定产生的动图旋转方向和角度来纠正。
最后是将帧列表保存为GIF格式的文件
# 保存帧列表为GIF文件
frames[0].save("snowfall.gif", save_all=True, append_images=frames[1:], duration=100, loop=0)
我们详细解释一下这段代码:
frames[0].save(“snowfall.gif”, save_all=True, append_images=frames[1:], duration=100, loop=0):这一行代码的目的是保存动画。具体说明如下:
import pygame
import random
from PIL import Image
# 初始化Pygame
pygame.init()
# 设置窗口尺寸和标题
window_width = 1280
window_height = 800
window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("雪花飘落")
# 定义雪花颜色为白色
WHITE = (255, 255, 255)
# 加载背景图片
background_image= pygame.image.load("snow.jpg")
# 创建雪花列表
snowflakes = []
# 创建雪花对象
class Snowflake:
def __init__(self, x, y, size):
self.x = x
self.y = y
self.size = size
self.speed = random.randint(1, 8)
def fall(self):
self.y += self.speed
if self.y > window_height:
self.y = random.randint(-50, -10)
self.x = random.randint(0, window_width)
def draw(self):
pygame.draw.circle(window, WHITE, (self.x, self.y), self.size)
# 创建GIF帧的列表
frames = []
# 主循环
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 清空窗口
# window.fill((0, 0, 0))
# 绘制背景图片
window.blit(background_image,(0,0))
# 生成雪花
# 控制生成雪花的数量
if len(snowflakes) < 100:
x = random.randint(0, window_width)
y = random.randint(0, window_height)
# 定义雪花的大小,1-5之间随机
size = random.randint(1, 5)
snowflake = Snowflake(x, y, size)
snowflakes.append(snowflake)
# 更新和绘制雪花
for snowflake in snowflakes:
snowflake.fall()
snowflake.draw()
# 刷新窗口
pygame.display.flip()
# 获取当前帧的截图并添加到帧列表
pygame_image = pygame.surfarray.array3d(pygame.display.get_surface())
pil_image = Image.fromarray(pygame_image)
pil_image = pil_image.rotate(-90,expand=True)
frames.append(pil_image.copy())
# 控制帧率
pygame.time.delay(10)
# 退出时关闭Pygame
pygame.quit()
# 保存帧列表为GIF文件
frames[0].save("snowfall.gif", save_all=True, append_images=frames[1:], duration=100, loop=0)