为了轻松保存游戏的游戏状态,我倾向于对包含所有游戏实体(也称为演员)的game对象进行序列化。

我遇到的一个常见问题是您不能腌制pygame surfaces,因此,如果您的actor类如下所示:

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模块对其进行腌制。

如何解决这个问题?

最佳答案

解决方案不是尝试序列化表面,而是将其从您的一个或多个游戏实体中移除并使用类似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(),然后才能对其进行序列化。



另一种方法是将角色的图形外包,因此您只需将标识符存储到角色中的曲面即可。

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)


但是,如果您的演员使用多个表面来代表自己,这会有些麻烦。

10-04 15:27