Search code examples
pygamepickledisplaysurface

Pickling a dictionary that contains pygame.Surface objects


So I have a dictionary called Images and it stores pygame.Surface objects. Instead of having to build this entire dictionary every time I run the code, I would just like to read it in from a file.

This is the code that I am trying to use to pickle and unpickle the dictionary:

with open('Images.pkl', 'wb') as output:
    pickle.dump(Images, output, pickle.HIGHEST_PROTOCOL)

with open('Images.pkl', 'rb') as input:
    Images = pickle.load(input)

Later on, I use this code:

class Survivor:
    def __init__(self):
        self.body_image=Images['Characters/Survivor/handgun/idle0']
        self.body_rect=self.body_image.get_rect()

which gives me:

File "ZombieSurvival.py", line 1320, in init self.body_rect=self.body_image.get_rect(center=self.vector)
pygame.error: display Surface quit


Solution

  • I was able to pickle the dictionary by first using pygame's pygame.image.tostring() function to convert every pygame.Surface in the dictionary Images, to a string, using pygame.image.tostring(). Then I pickled Images. Whenever I want to use Images, I unpickle it and convert every string in it back go a pygame.Surface using pygame.image.fromstring().

    However, pygame.image.fromstring() requires us to tell it the size of the pygame.Surface that it is about to convert, so I saved the sizes of each pygame.Surface before I used the pyame.image.tostring() function.

    On every occasion where I was about to call pygame.image.tostring() on a pygame.Surface, I first stored the pygame.Surface's key (it's location in Images) and its size in an instance of a class with fields key and size. I stored every instance of this class in a list called list_of_image_sizes, and pickled the list.

    Now, when you use the pygame.image.fromstring() function, you can call it as such:

    for data in list_of_image_sizes:
        Images[data.key]=pygame.image.fromstring(Image[data.key], data.size, 'RGBA')   
        #RGBA is my particular argument, you can change it as you wish