Python练习题 13-3/4:雨滴/连绵细雨
任务描述:
1、找一幅雨滴图像
2、创建一系列整齐排列的雨滴
3、让这些雨滴下落
4、到达屏幕底端后消失
5、雨滴全部消失后再生成雨滴
思路分析:
1、设置程序运行前提条件
2、创建雨滴类并配置相关属性
3、显示雨滴多行多列显示
4、雨滴多行下落
5、雨滴出界删除后带空屏时重新生产
编码结构分析:
1、设置主程序存放在类StarList中并存储在文件case13-3.py文件中
2、创建Rains类存在rain.py中
程序代码如下:
1、主程序
# @Time : 2021/3/25 14:42
# @Author : ly
# @Project : pycharmpractise
# @GitHub : https://github.com/lxcl96
import sys
import pygame
from rains import Rains
class Rains_Drop:
"""
1、找一幅雨滴图像
2、创建一系列整齐排列的雨滴
3、让这些雨滴下落
4、到达屏幕底端后消失
5、雨滴全部消失后再生成雨滴
"""
def __init__(self):
# 初始化模块
pygame.init()
# 设置屏幕大小
self.screen = pygame.display.set_mode((800, 600))
# 设置窗口标题
pygame.display.set_caption(" Rains Dropping")
# 更新雨滴后需要不断更新屏幕
# self.screen.fill((246, 246, 246))
# 设置精灵组
self.rains = pygame.sprite.Group()
# 重点 必须要在这个使用 因为在这里就创建一次 否则在while中会一直循环
# 创建雨滴成雨
self._create_rains()
# print(len(self.rains))
# 排列显示函数
def _range_rain(self,number_x, number_y):
# 双重循环创建
for now_number_y in range(number_y):
for now_number_x in range(number_x):
# 实例化
rain_drops = Rains(self)
# 设置每个具体雨滴的位置
# 必须要有 rain_drops.rect.x = rain_drops.x 和 rain_drops.rect.y = rain_drops.y
# 因为只有这样 才能 让多行雨滴同时下落
# 而且 必须是 rain_drops.x 这个从 Rains 带过来表述 图片位置的 的 变量
rain_drops.x = rain_drops.image_width * now_number_x * 2 + rain_drops.image_width
rain_drops.rect.x = rain_drops.x
rain_drops.y = rain_drops.image_height * now_number_y * 2 + rain_drops.image_width
rain_drops.rect.y = rain_drops.y
self.rains.add(rain_drops)
# 计算每行可以容纳的雨滴数
def _create_rains(self):
"""计算多行多列雨滴数"""
# 获取屏幕宽度 和 高度的三分之一
# 实例化类
rain_drop = Rains(self)
self.screen_width = self.screen.get_width()
self.screen_height_separate = self.screen.get_height() / 3
# 计算每行 可以利用的 空间除去两边的 边距
allow_space_x = self.screen_width - rain_drop.image_width * 2
allow_space_y = self.screen_height_separate
# 计算每行 可以显示个数 整除 //
allow_number_x = int(allow_space_x // (2 * rain_drop.image_width))
# print(allow_number_x)
allow_number_y = int(allow_space_y // (rain_drop.image_height * 2))
self._range_rain(allow_number_x, allow_number_y)
def _check_edge(self):
"""判断雨滴是否越界 如果越界了将其删除 ,如果雨下完了就重新下雨"""
for rain in self.rains.sprites():
if rain.rect.top >= self.screen.get_rect().bottom:
self.rains.remove(rain)
print("该雨滴已经去除,面前组内剩余雨滴数:" + str(len(self.rains)))
# 重新下雨
if len(self.rains) == 0:
self._create_rains()
def run_game(self):
while True:
# 此处为程序退出
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# 判断雨滴是否越界 如果越界了将其删除 ,如果雨下完了就重新下雨
self._check_edge()
# 下落成雨
self.rains.update()
self.screen.fill((246, 246, 246))
# 显示出雨滴
self.rains.draw(self.screen)
# 显示屏幕
pygame.display.flip()
"""
本次程序编写遇到几种问题现整理如下:
1、页面只显示一行雨滴
A:创建雨滴 位置 需要指定 雨滴的 x轴和 y轴
2、7行雨滴结果只有第一行下落,底面六行雨滴不动
A:指定雨滴位置x轴和y轴 变量问题导致的 必须要要使用Rains类中的 self.y = float(self.rect.y) 和self.x = float(self.rect.x)指定位置
定义别的变量如 rain_drops_x 来代替 rain_drops.x 是不行的
这是因为 rain_drops.x 代表每个雨滴的位置的x轴 而 rain_drops_x 只代表 一个变量而已不会记录位置信息 只有值 虽然他俩的值是相同的
同样y轴也要这样使用 所有在Rains类中声明了两个 雨滴的同xy轴变量
3、雨滴下落页面会出现一条实线
A:没有动态更新背景 将其放在while循环中即可
4、页面生成的雨滴不下落
A:将需要将雨滴的创建和绘制分开。即雨滴的创建函数_create_rains()只使用一次在 __init__中使用
但是 动态的显示/绘制雨滴 在while中循环
"""
if __name__ == '__main__':
rains_drop = Rains_Drop()
rains_drop.run_game()
2、Rain类
# @Time : 2021/3/25 16:18
# @Author : ly
# @Project : pycharmpractise
# @GitHub : https://github.com/lxcl96
import pygame
from pygame.sprite import Sprite
class Rains(Sprite):
"""此出上传雨滴图像 并配置相关属性"""
def __init__(self, ai_game):
# 继承类
super().__init__()
# 上传图片
self.image = pygame.image.load('images/rain-247x3.png')
# 获取屏幕属性
self.screen = ai_game.screen
# 获取图片尺寸 屏幕尺寸
self.rect = self.image.get_rect()
self.screen_rect = self.screen.get_rect()
# 获取雨滴的宽度和长度
self.image_width = float(self.image.get_width())
self.image_height = float(self.image.get_height())
# 设置雨滴下落的速度
self.speed = 0.5
# 这样可以让 下落的速度变为小数 而且 必须要确定 self.x/y 的类型为位置类型因为只有这样才会 让多行雨滴进行下落 否则只有单行
self.y = float(self.rect.y)
self.x = float(self.rect.x)
# 更新雨滴移动
def update(self):
self.y += self.speed
self.rect.y = self.y
# self.rect.y += self.speed
运行结果:
疑难点分析:
1、页面只显示一行雨滴
A:创建雨滴 位置 需要指定 雨滴的 x轴和 y轴
2、4行雨滴结果只有第一行下落,底面3行雨滴不动
A:指定雨滴位置x轴和y轴 变量问题导致的 必须要要使用Rains类中的 self.y = float(self.rect.y) 和self.x = float(self.rect.x)指定位置
定义别的变量如 rain_drops_x 来代替 rain_drops.x 是不行的
这是因为 rain_drops.x 代表每个雨滴的位置的x轴 而 rain_drops_x 只代表 一个变量而已不会记录位置信息 只有值 虽然他俩的值是相同的
同样y轴也要这样使用 所有在Rains类中声明了两个 雨滴的同xy轴变量
3、雨滴下落页面会出现一条实线
A:没有动态更新背景 将其放在while循环中即可
4、页面生成的雨滴不下落
A:将需要将雨滴的创建和绘制分开。即雨滴的创建函数_create_rains()只使用一次在 __init__中使用
但是 动态的显示/绘制雨滴 在while中循环