Как сохранить объект с помощью pygame.Surfaces в файл с помощью pickle - PullRequest
0 голосов
/ 14 сентября 2018

Если я создал свой собственный класс с некоторыми атрибутами pygame.Surfaces и хотел бы сохранить этот объект в файл, как я могу это сделать, если при попытке произойдет ошибка.

Класс, который я создал, является объектом, который по существу является следующим (класс Предметов включен, потому что у игрока есть предметы, которые имеют атрибуты, которые являются 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

К вашему сведению, все, что я положил в фигурные скобки ({и}), это просто то, что я сократил или пропустил, потому что в этом не было необходимости

Если вам нужно больше подробностей, я могу легко добавить их, если вы ответите, что вам нужно

1 Ответ

0 голосов
/ 14 сентября 2018

pygame.Surface с не предназначены для маринования. Вы можете поместить свои изображения в словарь, чтобы получить их по их имени / ключу словаря (строка). Затем сохраните это имя в своем спрайте, чтобы сериализовать его с помощью pickle или json (что более безопасно) и использовать его для воссоздания спрайта при загрузке игры.

Вот простой пример, в котором вы можете сохранить и загрузить некоторые спрайты (только соответствующие атрибуты), нажав s и w :

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()
...