如何使用 pygame.Surfaces 将对象保存到使用 pickle 的文件中

How to save object using pygame.Surfaces to file using pickle

如果我创建了自己的 class,它有一些 pygame.Surfaces 的属性,我想将这个对象保存到一个文件中,我该如何做,因为当我试试。

我创建的 class 是一个对象,本质上是以下内容(包含项目 class 是因为播放器的项目具有 pygame.Surfaces 的属性):

class Item:
    def __init__(self,name,icon):
        self.name = name
        self.icon = pygame.image.load(icon)

class Player(pygame.Sprite):
    def __init__(self,{some_attrs})
        skins = [{a pygame.Surface from a load image},{another}]
        self.money = 0
        self.items = [{Item object}]

然后当我尝试保存时,我使用以下内容:

with open('save.dat','wb') as file:
    pickle.dump(player , file , protocol = 4)
    #I have also tried without the protocol argument

但我收到以下错误:

Traceback (most recent call last):
  File "{file path}", line 883, in <module>
    save_progress()
  File "{file path}", line 107, in save_progress
    pickle.dump(player,file,protocol=4)
TypeError: can't pickle pygame.Surface objects

仅供参考,我放在大括号({ 和 })中的所有内容都是我缩写或省略的内容,因为不需要

如果您需要更多详细信息,只要您回复您的需要,我可以轻松添加

pygame.Surfaces 不应该被腌制。您可以将图像放入字典中,以便可以通过它们的 name/dictionary 键(字符串)检索它们。然后将此名称存储在您的 sprite 中,以使用 pickle 或 json(更安全)将其序列化,并在您加载游戏时使用它重新创建 sprite。

这是一个简单的示例,您可以通过按 sw 来保存和加载一些精灵(仅相关属性):

import json
import pygame as pg


pg.init()
IMAGE_BLUE = pg.Surface((32, 52))
IMAGE_BLUE.fill(pg.Color('steelblue1'))
IMAGE_SIENNA = pg.Surface((32, 52))
IMAGE_SIENNA.fill(pg.Color('sienna1'))
# Put the images into a dictionary, so that we can get them by their name.
IMAGES = {'blue': IMAGE_BLUE, 'sienna': IMAGE_SIENNA}


class Entity(pg.sprite.Sprite):

    def __init__(self, pos, image_name):
        super().__init__()
        # Store the image name to save it with json later.
        self.image_name = image_name
        self.image = IMAGES[image_name]
        self.rect = self.image.get_rect(topleft=pos)


class Game:

    def __init__(self):
        self.done = False
        self.bg_color = pg.Color('gray13')
        self.clock = pg.time.Clock()
        self.screen = pg.display.set_mode((640, 480))
        # Pass the image names (i.e. keys of the IMAGES dict).
        entity1 = Entity((250, 120), 'blue')
        entity2 = Entity((400, 260), 'sienna')
        self.all_sprites = pg.sprite.Group(entity1, entity2)
        self.selected = None

    def run(self):
        while not self.done:
            self.handle_events()
            self.run_logic()
            self.draw()
            self.clock.tick(60)

    def handle_events(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.done = True
            elif event.type == pg.MOUSEBUTTONDOWN:
                if self.selected:
                    self.selected = None
                else:
                    for sprite in self.all_sprites:
                        if sprite.rect.collidepoint(event.pos):
                            self.selected = sprite
            elif event.type == pg.MOUSEMOTION:
                if self.selected:
                    self.selected.rect.move_ip(event.rel)
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_s:
                    self.save()
                elif event.key == pg.K_w:
                    self.load()

    def run_logic(self):
        self.all_sprites.update()

    def draw(self):
        self.screen.fill(self.bg_color)
        self.all_sprites.draw(self.screen)
        pg.display.flip()

    def save(self):
        with open('save_game1.json', 'w') as file:
            print('Saving')
            # Create a list of the top left positions and the
            # image names.
            data = [(sprite.rect.topleft, sprite.image_name)
                    for sprite in self.all_sprites]
            json.dump(data, file)

    def load(self):
        with open('save_game1.json', 'r') as file:
            print('Loading')
            data = json.load(file)
            self.selected = None
            self.all_sprites.empty()
            # Use the positions and image names to recreate the sprites.
            for pos, image_name in data:
                self.all_sprites.add(Entity(pos, image_name))


if __name__ == '__main__':
    Game().run()
    pg.quit()