python - pygame连续下雨

标签 python pygame

12/16 更新

这段代码获得了正确的效果,但我不知道在新项目new_rainnew_rain.y中没有row并且我从Group rains中删除rain,那么为什么当我将new_rain添加到rains中时,其中仍然有一行,对于我只设置了 new_rain.y = 0

def check_edge(setting,rains):
        for rain in rains.sprites():
            if rain.rect.y == setting.h:
                new_rain=Rain()
                new_rain.number=rain.number
                new_rain.row=rain.row
                new_rain.rect.x=new_rain.rect.x+rain.rect.width*new_rain.number
                new_rain.y = 0
                new_rain.rect.y=new_rain.y
                rains.add(new_rain)
                rains.remove(rain)

我正在做13-4练习连续下雨,我的想法是检查每次下雨的位置,首先我创建一个名为rainsGroup并将所有项目添加到其中,然后将其blit显示在屏幕上。

我还将数字和行存储到Group rains中,以便我可以为其他方法调用它

def create(self,setting,rains):
    spacex=setting.w-2*self.rect.x
    numbers=int(spacex/(2*self.rect.x))
    rows=int(setting.h/(4*self.rect.height))
    for row in range(rows):
        for number in range(numbers):
            rain=Rain()
            rain.number=number
            rain.row=row
            rain.rect.x =rain.rect.x+rain.rect.width*number
            rain.y = rain.rect.y+2*rain.rect.height*row
            rain.rect.y =rain.y
            rains.add(rain)

然后我检查位置,如果rains中的任何项目接触到底部,则删除该项目并在其中添加新项目,从而使持续下雨

def check_edge(self,setting,rains):
        for rain in rains.sprites():
            if rain.rect.y == setting.h:
                new_rain=Rain()
                new_rain.rect.x=new_rain.rect.x+rain.rect.width*rain.number
                new_rain.y =new_rain.rect.y+2*rain.rect.height*rain.row
                new_rain.rect.y=new_rain.y
                rains.remove(rain)
                rains.add(new_rain) 

我的屏幕上有 2 行和 10 列的雨,但是当我运行此脚本时,第一个和第二个循环是正确的,雨确实消失了,然后在屏幕上创建了新的雨

第三个循环显示错误AttributeError: 'Rain' object has no attribute 'number' 我尝试了很多次都找不到原因,因为我已经在Group

中定义了numberrow

代码如下:

#!/usr/bin/python
import sys
import pygame as p
from random import randint

#13-4

class Setting():
    def __init__(self,width,height):
        self.w=width
        self.h=height
        self.screen=p.display.set_mode((self.w,self.h),p.RESIZABLE,0)
        self.speed = 1
        p.display.set_caption("EXE 13-4")

class Rain(p.sprite.Sprite):
    def __init__(self):
        super().__init__()
        pic=p.image.load("../image/rain.jpg").convert_alpha()
        self.image=p.transform.smoothscale(pic,(100,100)).convert_alpha()
        self.rect=self.image.get_rect()
        self.rect.x=(self.rect.width)/2
        self.y=float(self.rect.y)
    def create(self,setting,rains):
        spacex=setting.w-2*self.rect.x
        numbers=int(spacex/(2*self.rect.x))
        rows=int(setting.h/(4*self.rect.height))
        for row in range(rows):
            for number in range(numbers):
                rain=Rain()
                rain.number=number
                rain.row=row
                rain.rect.x =rain.rect.x+rain.rect.width*number
                rain.y = rain.rect.y+2*rain.rect.height*row
                rain.rect.y =rain.y
                rains.add(rain)
        print(spacex)
        print(numbers)
    def check_edge(self,setting,rains):
        for rain in rains.sprites():
            if rain.rect.y == setting.h:
                new_rain=Rain()
                new_rain.rect.x=new_rain.rect.x+rain.rect.width*rain.number
                new_rain.y =new_rain.rect.y+2*rain.rect.height*rain.row
                new_rain.rect.y=new_rain.y
                rains.remove(rain)
                rains.add(new_rain)



    def update(self,setting):
        self.y += setting.speed
        self.rect.y= self.y
    def blit(setting,rains):
        rains.update(setting)
        rains.draw(setting.screen)


def game():
    p.init()
    setting=Setting(1200,800)
    rain=Rain()
    rains=p.sprite.Group()
    rain.create(setting,rains)
    while True:
        for event in p.event.get():
            if event.type == p.QUIT:
                sys.exit()
            elif event.type == p.KEYDOWN:
                if event.key == p.K_ESCAPE:
                    sys.exit()
        setting.screen.fill((0,0,255))

        rain.check_edge(setting,rains)
        Rain.blit(setting,rains)
        p.display.flip()
game()

最佳答案

主要问题是 new_rain 永远不会获取属性 .row.number。将属性 .number.rowrain 复制到 new_rain:

new_rain=Rain()
new_rain.number = rain.number
new_rain.row = rain.row
<小时/>

从循环中移除一个雨滴并在循环中放入一个新的雨滴是完全多余的。 改变雨滴的坐标就足够了。当雨滴到达地面时,将其移动到窗口顶部:

class Rain(p.sprite.Sprite):
    # [...]

    def check_edge(self,setting,rains):
        for rain in rains.sprites():
            if rain.rect.y == setting.h:
                # put the drop at the top of the window
                rain.y = 0
                rain.rect.y = 0
<小时/>

如果您确实想创建全新的雨滴,无论出于何种原因,您都必须将属性 .numberrain 复制到 new_rain。新雨滴的位置始终为 0,位于窗口顶部:

class Rain(p.sprite.Sprite):
    # [...]

    def check_edge(self,setting,rains):
        for rain in rains.sprites():
            if rain.rect.y == setting.h:

                new_rain=Rain()
                new_rain.number = rain.number

                new_rain.rect.x=new_rain.rect.x+rain.rect.width*new_rain.number
                new_rain.y = 0
                new_rain.rect.y=new_rain.y

                rain.kill() # or rains.remove(rain)
                rains.add(new_rain) 
<小时/>

对于初始位置,雨滴的行很重要,因为雨滴必须排列在不同的行中。雨滴的 y 坐标取决于行。
但是,一旦雨滴开始落下,初始行对于雨滴的 y 坐标就不再有意义。雨滴一开始放置在哪里是完全无关的。窗口顶部的 y 坐标为 0,如果雨滴必须从顶部落下,则其 y 坐标必须设置为 0。
请注意,如果创建了新的雨滴,则在最上面一行中,没有任何雨滴,因为它们已经落下。最上面一行是空的,必须将新的雨滴放置在那里。
属性 .row 根本不需要,可以删除。该行仅在应用程序启动时(即 create 创建雨滴时)才有意义。之后,雨滴落下,不断地改变着“行”。

关于python - pygame连续下雨,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59344763/

相关文章:

python - 制作简单的 flappy bird 游戏时如何修复错误 "TypeError: argument 1 must be pygame.Surface, not list"?

python 3 : Removing an empty tuple from a list of tuples

python - itertools.groupby 中组大小的限制

python - 在 python 2.7 中将电子邮件附件保存到文件

python - Sprite 向左移动的速度比向右移动的快

python - 在 Pygame 中跨屏幕移动对象

python - 如何在Python中绘制条形图

python - 如何在 expr() 中使用列名而不是直接值在 Pyspark 中添加日期?

python - 访问类(class)外的 Sprite /类(class)位置

python - 我如何知道 Pygame 中的圆和矩形是否被触摸?