首页 > 解决方案 > 在不同的x位置pygame产生一个类的多个实例

问题描述

我正在 pygame 中制作 Pong 克隆,但我无法生成桨。我的桨班看起来像这样:

class Paddle(pygame.sprite.Sprite, x_pos):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((20,70))
        self.image.fill(colors["WHITE"])
        self.rect = self.image.get_rect()
        self.rect.x = x_pos
        self.rect.y = SCREEN_HEIGHT/2
        self.y_speed = 0

我尝试在屏幕的相对两侧生成其中两个

player1 = Paddle(SCREEN_WIDTH - self.image.get_width() - 10) # Adjust for paddle width and border
player2 = Paddle(10)

但我得到了错误

Traceback (most recent call last):
  File "pypong.py", line 19, in <module>
    class Paddle(pygame.sprite.Sprite, x_pos):
NameError: name 'x_pos' is not defined

我尝试替换self.rect.x = x_pos为,self.rect.x_pos = self.x_pos但仍然遇到相同的错误。我以为我掌握了 OOP 的窍门,但这让我陷入了困境。有人可以帮忙吗?提前致谢。

标签: pythonpygame

解决方案


所以你定义的课程有一些问题,我认为值得先了解一些基础知识,然后再看看你的课程。我已将答案分为这两个部分,因此如果必须,您可以跳过。


python 类可以“看到”传递给它或在其中定义的变量。我们在__init__方法中进行传递和定义:

class Paddle:
    def __init__(self, x_pos):
        ...

请注意,该类本身不接受任何参数(它甚至没有括号!)。相反,我们将要在类中使用的所有参数传递给__init__方法!一个类可以用括号定义,但只有当它的类基于另一个类时,这称为派生类:

class pygame.sprite.Sprite:
    def __init__(self, ...):
        ...

class Paddle(pygame.sprite.Sprite):
    def __init__(self, ...):
        ...

接下来,我们已经看到我们可以通过类的__init__方法将变量传递给类,但是我们如何将它们作为属性存储在类中并在类方法(函数)中使用它们呢?我们通过在类属性前面加上self.这样的来做到这一点:

class Paddle(pygame.sprite.Sprite):
    def __init__(self, x_pos):
        ...
        self.x_position = x_pos

现在我们可以在类的其他方法中使用该属性,而不仅仅是在__init__方法中:

class Paddle(pygame.sprite.Sprite):
    def __init__(self, x_pos):
        ...
        self.x_position = x_pos

    def x_add_1(self):
        self.x_position += 1

方法内部的东西x_add_1()知道x_position属性,因为我们传递self给方法,这x_position是存储属性的地方(因为我们将其定义为self.x_position)。

所以现在我们有一个类,有一个属性(self.x_position)和一个方法(x_add_1),让我们通过创建一个类的实例来使用它:

class Paddle(pygame.sprite.Sprite):
    def __init__(self, x_pos):
        ...
        self.x_position = x_pos

    def x_add_1(self):
        self.x_position += 1

player_1 = Paddle(5)
print(player1.x_position)
> 5
player1.x_add_1()
print(player1.x_position)
> 6

现在你可以看到我们是如何创建一个类的实例,并将值 5Paddle传递给它的。然后我们访问实例的属性,并使用该方法。x_posx_positionplayer_1x_add_1


现在让我们看看你在哪里遇到了一些麻烦:

class Paddle(pygame.sprite.Sprite, x_pos):
    def __init__(self):
    ...

首先,您已经创建Paddlepygame.sprite.Sprite. 这似乎是合理的。但是你也传递了它x_pos,它应该传递给__init__你没有传递任何东西的方法!这就是为什么您会收到x_pos未定义错误的原因,因为该__init__方法已被告知使用它但尚未通过它。

但是一旦我们解决了这个问题,我们仍然遇到了麻烦:

class Paddle(pygame.sprite.Sprite):
    def __init__(self, x_pos):
        ...
        self.image.fill(colors["WHITE"])
        self.rect.y = SCREEN_HEIGHT/2

你的班级没有被告知有一个名为 的字典colors,也没有一个名为 的整数SCREEN_HEIGHT。为了能够使用它们,必须在实例化类时传递它们。

class Paddle(pygame.sprite.Sprite):
    def __init__(self, x_pos, colors, SCREEN_HEIGHT):
        ...
        self.image.fill(colors["WHITE"])
        self.rect.y = SCREEN_HEIGHT/2

如果您认为不会在__init__方法之外使用它们,则不必将这些新变量存储为类属性,但您可以。例如,您可能希望在球击中球拍时使球拍变红,在这种情况下,您需要创建一个属性来存储colors字典:

class Paddle(pygame.sprite.Sprite):
    def __init__(self, x_pos, colors, SCREEN_HEIGHT):
        self.colors = colors
        ...
        self.image.fill(self.colors["WHITE"])
        self.rect.y = SCREEN_HEIGHT/2

    def paddle_hit(self):
        ...
        self.image.fill(self.colors["RED"])
        ...

这可能是您修复课程所需要知道的全部内容。恐怕我没有给你任何你可以复制和粘贴的东西,但我已经强调了我能看到的所有问题(我认为)并描述了如何解决它们!


推荐阅读