内置文件sprite.py出错怎么办?

What should I do if the built-in file, sprite.py, gets an error?

我是 python 编码的新手(我今年 11 岁),正在一个帮助新编码员制作他们的第一款游戏的网站上练习,但我在 sprite.py 中偶然发现了一个错误.我不确定如何处理的原因是 sprite.py 内置于我下载的 python 文件中。错误消息表明 add_internal() 缺少必需的位置参数:'sprite'。我不太确定如何解决这个问题,因为我没有创建或编码 sprite.py,也没有对文件进行任何编辑。这是我的错误消息:

Traceback (most recent call last):
  File "C:\Users\aveil\Desktop\CodaKid Python 2\PEW PEW ROBO MASSACRE\src\main.py", line 46, in <module>
    PowerUp(screen, 300, 700)
  File "C:\Users\aveil\Desktop\CodaKid Python 2\PEW PEW ROBO MASSACRE\src\powerup.py", line 7, in __init__
    pygame.sprite.Sprite.__init__(self, self.containers)
  File "C:\Users\aveil\AppData\Roaming\Python\Python36\site-packages\pygame\sprite.py", line 124, in __init__
    self.add(groups)
  File "C:\Users\aveil\AppData\Roaming\Python\Python36\site-packages\pygame\sprite.py", line 142, in add
    self.add(*group)
  File "C:\Users\aveil\AppData\Roaming\Python\Python36\site-packages\pygame\sprite.py", line 139, in add
    group.add_internal(self)
TypeError: add_internal() missing 1 required positional argument: 'sprite'.

我不确定如何处理此错误,但检查了 sprite.py 以查看是否有任何我可以解决的问题。我没有发现我知道如何修复的错误。

这是来自 Traceback 错误的代码。我还包括解释上下文代码的注释。为冗长的代码片段道歉。

##    pygame - Python Game Library
##    Copyright (C) 2000-2003, 2007  Pete Shinners
##              (C) 2004 Joe Wreschnig
##    This library is free software; you can redistribute it and/or
##    modify it under the terms of the GNU Library General Public
##    License as published by the Free Software Foundation; either
##    version 2 of the License, or (at your option) any later version.
##
##    This library is distributed in the hope that it will be useful,
##    but WITHOUT ANY WARRANTY; without even the implied warranty of
##    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
##    Library General Public License for more details.
##
##    You should have received a copy of the GNU Library General Public
##    License along with this library; if not, write to the Free
##    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##
##    Pete Shinners
##    pete@shinners.org

"""pygame module with basic game object classes

This module contains several simple classes to be used within games. There
are the main Sprite class and several Group classes that contain Sprites.
The use of these classes is entirely optional when using Pygame. The classes
are fairly lightweight and only provide a starting place for the code
that is common to most games.

The Sprite class is intended to be used as a base class for the different
types of objects in the game. There is also a base Group class that simply
stores sprites. A game could create new types of Group classes that operate
on specially customized Sprite instances they contain.

The basic Sprite class can draw the Sprites it contains to a Surface. The
Group.draw() method requires that each Sprite have a Surface.image attribute
and a Surface.rect. The Group.clear() method requires these same attributes
and can be used to erase all the Sprites with background. There are also
more advanced Groups: pygame.sprite.RenderUpdates() and
pygame.sprite.OrderedUpdates().

Lastly, this module contains several collision functions. These help find
sprites inside multiple groups that have intersecting bounding rectangles.
To find the collisions, the Sprites are required to have a Surface.rect
attribute assigned.

The groups are designed for high efficiency in removing and adding Sprites
to them. They also allow cheap testing to see if a Sprite already exists in
a Group. A given Sprite can exist in any number of groups. A game could use
some groups to control object rendering, and a completely separate set of
groups to control interaction or player movement. Instead of adding type
attributes or bools to a derived Sprite class, consider keeping the
Sprites inside organized Groups. This will allow for easier lookup later
in the game.

Sprites and Groups manage their relationships with the add() and remove()
methods. These methods can accept a single or multiple group arguments for
membership.  The default initializers for these classes also take a
single group or list of groups as argments for initial membership. It is safe
to repeatedly add and remove the same Sprite from a Group.

While it is possible to design sprite and group classes that don't derive
from the Sprite and AbstractGroup classes below, it is strongly recommended
that you extend those when you create a new Sprite or Group class.

Sprites are not thread safe, so lock them yourself if using threads.

"""

##todo
## a group that holds only the 'n' most recent elements.
## sort of like the GroupSingle class, but holding more
## than one sprite
##
## drawing groups that can 'automatically' store the area
## underneath so they can "clear" without needing a background
## function. obviously a little slower than normal, but nice
## to use in many situations. (also remember it must "clear"
## in the reverse order that it draws :])
##
## the drawing groups should also be able to take a background
## function, instead of just a background surface. the function
## would take a surface and a rectangle on that surface to erase.
##
## perhaps more types of collision functions? the current two
## should handle just about every need, but perhaps more optimized
## specific ones that aren't quite so general but fit into common
## specialized cases.

import pygame
from pygame import Rect
from pygame.time import get_ticks
from operator import truth

# Python 3 does not have the callable function, but an equivalent can be made
# with the hasattr function.
if 'callable' not in dir(__builtins__):
    callable = lambda obj: hasattr(obj, '__call__')

# Don't depend on pygame.mask if it's not there...
try:
    from pygame.mask import from_surface
except:
    pass


class Sprite(object):
    """simple base class for visible game objects

    pygame.sprite.Sprite(*groups): return Sprite

    The base class for visible game objects. Derived classes will want to
    override the Sprite.update() method and assign Sprite.image and Sprite.rect
    attributes.  The initializer can accept any number of Group instances that
    the Sprite will become a member of.

    When subclassing the Sprite class, be sure to call the base initializer
    before adding the Sprite to Groups.

    """

    def __init__(self, *groups):
        self.__g = {} # The groups the sprite is in
        if groups:
            self.add(*groups)

    def add(self, *groups):
        """add the sprite to groups

        Sprite.add(*groups): return None

        Any number of Group instances can be passed as arguments. The
        Sprite will be added to the Groups it is not already a member of.

        """
        has = self.__g.__contains__
        for group in groups:
            if hasattr(group, '_spritegroup'):
                if not has(group):
                    group.add_internal(self)
                    self.add_internal(group)
            else:
                self.add(*group)

    def remove(self, *groups):
        """remove the sprite from groups

        Sprite.remove(*groups): return None

        Any number of Group instances can be passed as arguments. The Sprite
        will be removed from the Groups it is currently a member of.

        """
        has = self.__g.__contains__
        for group in groups:
            if hasattr(group, '_spritegroup'):
                if has(group):
                    group.remove_internal(self)
                    self.remove_internal(group)
            else:
                self.remove(*group)

    def add_internal(self, group):
        self.__g[group] = 0

    def remove_internal(self, group):
        del self.__g[group]

    def update(self, *args):
        """method to control sprite behavior

        Sprite.update(*args):

        The default implementation of this method does nothing; it's just a
        convenient "hook" that you can override. This method is called by
        Group.update() with whatever arguments you give it.

        There is no need to use this method if not using the convenience
        method by the same name in the Group class.

        """
        pass

    def kill(self):
        """remove the Sprite from all Groups

        Sprite.kill(): return None

        The Sprite is removed from all the Groups that contain it. This won't
        change anything about the state of the Sprite. It is possible to
        continue to use the Sprite after this method has been called, including
        adding it to Groups.

        """
        for c in self.__g:
            c.remove_internal(self)
        self.__g.clear()

    def groups(self):
        """list of Groups that contain this Sprite

        Sprite.groups(): return group_list

        Returns a list of all the Groups that contain this Sprite.

        """
        return list(self.__g)

    def alive(self):
        """does the sprite belong to any groups

        Sprite.alive(): return bool

        Returns True when the Sprite belongs to one or more Groups.
        """
        return truth(self.__g)

    def __repr__(self):
        return "<%s sprite(in %d groups)>" % (self.__class__.__name__, len(self.__g))

如有任何帮助,我将不胜感激。提前致谢!

这是@Kingsly 的 PowerUp init() 语句,感谢您的帮助!

import pygame
import random
import toolbox

class PowerUp(pygame.sprite.Sprite):
    def __init__(self, screen, x, y):
        pygame.sprite.Sprite.__init__(self, self.containers)
        self.screen = self.screen
        self.x = x
        self.y = y
        self.pick_power = random.randint(0, 0)
        if self.pick_power == 0: #Crate ammo
            self.image = pygame.image.oad("../update/powerupCrate.png")
            self.background_image = pygame.image.load("../assets/powerupBackgroundBlue.png")
            self.power_type = 'crateammo'
        self.rect = self.image.get_rect()
        self.rect.center = (self.x, self.y)
        self.background_angle =  0
        self.spinny_speed = 2

    def update(self):
        self.background_angle += self.spinny_speed
        bg_image_to_draw, bg_rect = toolbox,getRotatedImage(self.background_image, self.rect, self.background_angle)


        self.screen.blit(bg_image_to_draw, bg_rect)
        self.screen.blit(self.image, self.rect)


我怀疑问题可能出在您的 PowerUp 初始化函数中的基础对象 __init__ 调用。通常 class pygame.sprite.Sprite.__init__() 函数仅在每个传递 pygame.sprite.Group 时出现,代表这个新精灵应该属于的组对象。

所以可能在您的代码中的某个地方,有类似的东西:

power_up_group     = pygame.sprite.group                 # <-- BUG!
PowerUp.containers = power_up_group

理论上会导致新的 PowerUp 精灵自动添加到 power_up_group 精灵组。

但是,您在语句末尾留下了 (),它应该是:

power_up_group = pygame.sprite.group()                   # <-- FIXED

您看到的错误是因为,没有 (),它不会创建新的组对象,只是传递如何创建组的定义。

像这样设置一个 class 成员不是一个很好的编程习惯,因为它使代码的可读性更差,更复杂,没有任何实际好处。任何组都可以作为参数传递给精灵__init__()然后传递给基础初始化器。这样可以更清楚地看到初始化程序中发生了什么,因为我们不必四处寻找代码来确定 self.containers 可能被设置为什么。

class PowerUp(pygame.sprite.Sprite):
    def __init__(self, screen, x, y, power_up_group):
        pygame.sprite.Sprite.__init__(self, power_up_group)     
        self.screen = self.screen
        # [...]

但是,如果您不使用任何精灵组容器逻辑,也可以将其从您的 class 代码中删除:

class PowerUp(pygame.sprite.Sprite):
    def __init__(self, screen, x, y):
        pygame.sprite.Sprite.__init__(self)      # <-- HERE, no containers
        self.screen = self.screen
        # [...]

您可以在精灵创建后将它们添加到精灵组中。通常这就是我的做法,因为很明显发生了什么事。