我应该如何序列化包含pygame表面的游戏对象?

时间:2012-08-17 13:22:41

标签: python pygame

为了轻松保存游戏的游戏状态,我倾向于序列化包含所有游戏实体(a.k.a. actors)的game对象。

我遇到的一个常见问题是你不能挑剔pygame surfaces,所以如果你的演员类看起来像这样:

class Actor(object):

  def __init__(self, **kwargs):
      self._image = kwargs['image']
      self.pos = kwargs['pos']
      ...

  def act(self):
      ...

  def draw(self, surface):
      surface.blit(self._image, self.pos)

你不能只用python pickle/cpickle模块来腌制它。

如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

解决方案不是尝试序列化曲面,而是将其从游戏/游戏实体中删除,并使用lazy loading之类的技术,例如恢复游戏状态后再次获得它们。

因此,不是将表面直接传递给实体,而是传递一个负责存储/检索表面的对象:

class Actor(object):

  def __init__(self, **kwargs):
    self._image_getter = kwargs['image_getter']
    self.pos = kwargs['pos']
    ...

  def draw(self, surface):
    surface.blit(self._image_getter(), self.pos)

image getter可能如下所示:

class SurfaceCapsule (object):

    def __init__(self, resource_manager, key):
        self._res = resource_manager
        self._key = key

    def __call__(self):
        return self._res[self._key]

请注意,我在这里使用了一个类,因为方法本身也不可用。

而不是像这样创建你的实体:

actor = Actor(image=resource_manager[key])

你会像这样创建它们:

actor = Actor(image_getter=SurfaceCapsule(resource_manager, key))

其中resource_manager将是管理游戏所有表面的对象。

class RessourceManager(dict):

    def __getitem__(self, key):
        # implement lazy loading if you want, or load all images at startup
        # load surface is necessary, cache it, and return it

    def __load_surface_by_key(key):
        # load stuff

在保存游戏状态之前,您必须clear(),然后您可以快乐地将其序列化。


另一种方法是将actor的绘图外包,因此您只需将标识符存储到actor中的曲面上。

class Actor(object):

  def __init__(self, **kwargs):
    self.image_key = kwargs['image_key']

并在你的游戏课程中:

def draw(self):
    for actor in self._actors:
        self._screen.blit(resource_manager[actor.image_key], actor.pos)

但如果你的演员使用多个表面代表他们自己,这有点麻烦。