【问题标题】:How to deepcopy object which contains pygame.Surface?如何深度复制包含 pygame.Surface 的对象?
【发布时间】:2019-07-26 18:53:10
【问题描述】:

我正在用 pygame 编写一个 2D 游戏引擎,但我在编写 spawner 类时遇到了困难。 我想要实现的是一种创建 spawner 的简单方法,例如:

bullet = Bullet()
spawner = Spawner()
spawner.set_spawn_object(bullet)

我在 set_spawn_object 中使用 copy.deepcopy

基本上我想将一个对象传递给 spawner,它应该对该对象进行深度复制并保存该副本。然后每隔 n 秒,它将通过将其复制到渲染碰撞的游戏对象的全局列表中来生成该对象。我需要一个深度复制,因为我想稍后单独修改它们(例如位置、名称、纹理)。问题是不能以这种方式复制表面。

现在我的游戏引擎中的每个对象都有自己的表面,我计划做的是将所有表面放在一个单独的类中以提高效率。这可以解决这个问题,因为我不会复制表面。但是……

假设我有一个 bullet 和一个 resource_manager 对象。 bullet 有一个指向 resource_manager.bullet_texture 的指针(它是一个 pygame.Surface)。

那我可以 bullet2=copy.deepcopy(bullet) 因为我会复制指针,而不是表面本身。

问题是python没有指针,我该怎么办?

【问题讨论】:

    标签: python pygame deep-copy


    【解决方案1】:

    您不能在pygame.Surface 上使用copy 模块,但Surface 有自己的Surface.copy 方法。

    您可以为您的类定义一个 copy 方法,该方法使用 Surface 实例的 Surface.copy 方法创建一个包含所有所需属性的副本的新实例。

    如果你有很多属性,你可以使用特殊的内置属性__dict__:它包含一个属性(键)及其值的字典,你可以遍历它来为每个属性分配一个副本原件。

    一个非常简单的例子:

    class Myobject:
        def __init__(self, image=None, rect=None):
            self.image = image #a pygame surface
            self.rect = rect #a rectangle
            self.level = 0
    
        def copy(self):
            copyobj = Myobject()
            for name, attr in self.__dict__.items():
                if hasattr(attr, 'copy') and callable(getattr(attr, 'copy')):
                    copyobj.__dict__[name] = attr.copy()
                else:
                    copyobj.__dict__[name] = copy.deepcopy(attr)
            return copyobj
    

    现在如果你这样做:

    myobj = Myobject(an_image, a_rectange)
    myobj2 = myobj.copy()
    

    myobj2myobj 的“副本”。它的 image 和 rect 是具有相同值的不同实例,您可以安全地编辑后者,而前者保持不变。

    所以,如果你想创建一个 spawner,spawner 可能会调用传递对象的 copy 方法。

    class Spawner:
        @staticmethod
        def set_spawn_object(obj):
            return obj.copy()
    

    【讨论】:

    • 不幸的是,在我的情况下,该类有许多变量,我不能手动复制所有内容。我也有许多继承自它并添加更多变量的类。有没有其他办法?
    • 好吧,如果你使用newsurface = oldsurface,那么newsurface 是对oldsurface 引用的同一表面的引用。它们指向同一个对象。
    • 所以我可以在表面上使用常规复制,在其他东西上使用深度复制。我可以以某种方式遍历所有类变量并检查当前变量是否是表面并决定使用哪个副本?如何实现?
    • 如果你可以在属性上使用不同的方法,那么我会使用Surface.copy() 来获取Surface 的副本,而对于非pygame 的东西使用deepcopy。但是,如果您可以拆分,我仍然建议使用我在回答中提到的copy 方法。您始终可以在类 copy 方法中使用 deepcopy
    • 对不起,我已经读过了。是的,您可以遍历类属性。让我编辑我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 1970-01-01
    • 2011-07-25
    • 2012-12-15
    相关资源
    最近更新 更多