首页 > 解决方案 > 如果内置文件 sprite.py 出错怎么办?

问题描述

我是 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)


标签: pythonpygamesprite

解决方案


我怀疑问题可能是__init__您的 PowerUp 初始化函数中的基本对象调用。通常,类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

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

像这样设置一个类成员并不是一个很好的编程习惯,因为它使代码的可读性降低并且更复杂而没有真正的收获。任何组都可以作为参数传递给 sprite __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
        # [...]

但是,如果您不使用任何 sprite-group 容器逻辑,也可以将其从您的类代码中删除:

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

您可以在创建精灵后将它们添加到精灵组中。一般来说,我就是这样做的,因为很明显发生了什么。


推荐阅读