我正在使用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
您是否知道如何将这些项目传输到服务器。或绕过这个泡菜限制?
如果我想保存零件会出现同样的问题,所以保存这些对象
答案 0 :(得分:2)
这是@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)
要查看可用于将数据存储为字符串的模式(此处为&#34; RGB&#34;),请查看into the documentation
答案 1 :(得分:0)
基于@MegaIng的答案,我制定了他/她的答案,以便您可以正常使用pygame.Surface,但添加了pickle功能。它不应打扰您的任何代码。我已经在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
P.s:
我还添加了功能,通过执行newSurface = PickleableSurface(PygameSurface)
,将无法上刺的pygame表面转换为可以上酱的表面
但是,它仅测试了一次,因此可能存在一些错误。如果您找到一个,请随时告诉我!希望对您有所帮助! :D