![](/img/trans.png)
[英]Pickle is saying it can't pickle a pygame.surface, but my object isn't a pygame.surface
[英]can't serialized pygame.Surface objects with pickle
我正在使用 python 3.6 开发游戏,我希望在它的多人游戏版本中发送到由客户端(玩家)修改的服务器对象,我想将它们序列化以进行传输。 我在我的对象中使用 pygame 和 pygame.Surface
我有这种结构的对象:
class Cargo(Bateau):
dictCargos = dict()
def __init__(self, map, nom, pos, armateur=None):
Bateau.__init__(self, map, nom, armateur, pos)
self.surface = pygame.image.load(f"images/{self.nom}.png").convert_alpha()
self.rect = self.map.blit(self.surface, self.pos)
...
Cargo.dictCargos[self.nom] = self
当我在没有 pygame 实例的情况下序列化另一个对象时,没关系但是对于上述对象,我收到此错误消息:
import pickle as pickle
pickle.dump(Cargo.dictCargos, open('file2.pkl', 'wb'), protocol=pickle.HIGHEST_PROTOCOL)
Traceback (most recent call last):
File "./pytransit.py", line 182, in <module>
encreG(joueur, event)
File "/home/patrick/Bureau/PyTransit/modulesJeu/tests.py", line 25, in encreG
pickle.dump(Cargo.dictCargos, open('file2.pkl', 'wb'), protocol=pickle.HIGHEST_PROTOCOL)
TypeError: can't pickle pygame.Surface objects
您知道如何将这些项目传输到服务器吗? 或者绕过这个泡菜限制?
如果我想保存一个零件也会出现同样的问题,所以保存这些对象
这是@IonicSolutions 在评论中指出的示例:
import pickle
import pygame
class Test:
def __init__(self, surface):
self.surface = surface
self.name = "Test"
def __getstate__(self):
state = self.__dict__.copy()
surface = state.pop("surface")
state["surface_string"] = (pygame.image.tostring(surface, "RGB"), surface.get_size())
return state
def __setstate__(self, state):
surface_string, size = state.pop("surface_string")
state["surface"] = pygame.image.fromstring(surface_string, size, "RGB")
self.__dict__.update(state)
t = Test(pygame.Surface((100, 100)))
b = pickle.dumps(t)
t = pickle.loads(b)
print(t.surface)
要查看可以使用哪些模式将数据存储为字符串(此处为“RGB”),请查看文档
根据@MegaIng 的回答,我开发了他/她的回答,以便您可以正常使用 pygame.Surface,但添加了泡菜功能。 它不应该打扰您的任何代码。 我已经在 python 3.7、64 位上对其进行了测试,并且可以正常工作。 也曾在我的项目中尝试/实施过,没有受到任何干扰。
import pygame as pg
pgSurf = pg.surface.Surface
class PickleableSurface(pgSurf):
def __init__(self, *arg,**kwarg):
size = arg[0]
# size given is not an iterable, but the object of pgSurf itself
if (isinstance(size, pgSurf)):
pgSurf.__init__(self, size=size.get_size(), flags=size.get_flags())
self.surface = self
self.name='test'
self.blit(size, (0, 0))
else:
pgSurf.__init__(self, *arg, **kwarg)
self.surface = self
self.name = 'test'
def __getstate__(self):
state = self.__dict__.copy()
surface = state["surface"]
_1 = pg.image.tostring(surface.copy(), "RGBA")
_2 = surface.get_size()
_3 = surface.get_flags()
state["surface_string"] = (_1, _2, _3)
return state
def __setstate__(self, state):
surface_string, size, flags = state["surface_string"]
pgSurf.__init__(self, size=size, flags=flags)
s=pg.image.fromstring(surface_string, size, "RGBA")
state["surface"] =s;
self.blit(s,(0,0));self.surface=self;
self.__dict__.update(state)
这是一个例子
pg.Surface = PickleableSurface
pg.surface.Surface = PickleableSurface
surf = pg.Surface((300, 400), pg.SRCALPHA|pg.HWSURFACE)
# Surface, color, start pos, end pos, width
pg.draw.line(surf, (0,0,0), (0,100), (200, 300), 2)
from pickle import loads, dumps
dump = dumps(surf)
loaded = loads(dump)
pg.init()
screen = pg.display.set_mode((300, 400))
screen.fill((255, 255, 255))
screen.blit(loaded, (0,0))
pg.display.update()
然后在我的屏幕上:
谢谢@MegaIng
Ps:我还通过newSurface = PickleableSurface(PygameSurface)
添加了将newSurface = PickleableSurface(PygameSurface)
腌制的 pygame 表面转换为可腌制的表面的功能,但是,它只测试了一次,因此可能存在一些错误。 如果你找到了,请随时告诉我! 我希望它会帮助你! :D
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.