0

我正在开发一款游戏,您可以在其中创建迷宫。您将块放置在 16x16 网格上,同时从各种块中进行选择以制作关卡。每当您创建一个块时,它都会添加此类:

class Block(object):
    def __init__(self,x,y,spr):
        self.x=x
        self.y=y
        self.sprite=spr
        self.rect=self.sprite.get_rect(x=self.x,y=self.y)

到一个名为instances.

我尝试将它搁置到 .bin 文件中,但它返回一些处理表面的错误。如何保存和加载关卡?

任何帮助表示赞赏!:)

这是整个代码供参考:

import pygame
from pygame.locals import *

#initstuff
pygame.init()
screen=pygame.display.set_mode((640,480))
pygame.display.set_caption('PiMaze')
instances=[]

#loadsprites
menuspr=pygame.image.load('images/menu.png').convert()
b1spr=pygame.image.load('images/b1.png').convert()
b2spr=pygame.image.load('images/b2.png').convert()
currentbspr=b1spr
curspr=pygame.image.load('images/curs.png').convert()
curspr.set_colorkey((0,255,0))

#menu
menuspr.set_alpha(185)
menurect=menuspr.get_rect(x=-260,y=4)

class MenuItem(object):
    def __init__(self,pos,spr):
        self.x=pos[0]
        self.y=pos[1]
        self.sprite=spr
        self.pos=(self.x,self.y)
        self.rect=self.sprite.get_rect(x=self.x,y=self.y)

class Block(object):
    def __init__(self,x,y,spr):
        self.x=x
        self.y=y
        self.sprite=spr
        self.rect=self.sprite.get_rect(x=self.x,y=self.y)

while True:
    #menu items
    b1menu=b1spr.get_rect(x=menurect.left+32,y=48)
    b2menu=b2spr.get_rect(x=menurect.left+64,y=48)
    menuitems=[MenuItem(b1menu,b1spr),MenuItem(b2menu,b2spr)]

    screen.fill((20,30,85))
    mse=pygame.mouse.get_pos()
    key=pygame.key.get_pressed()
    placepos=((mse[0]/16)*16,(mse[1]/16)*16)
    if key[K_q]:
        if mse[0]<260:
            if menurect.right<255:
                menurect.right+=1
        else:
            if menurect.left>-260:
                menurect.left-=1
    else:
        if menurect.left>-260:
            menurect.left-=1
    for e in pygame.event.get():
        if e.type==QUIT:
            exit()

        if menurect.right<100:
            if e.type==MOUSEBUTTONUP:
                if e.button==1:
                    to_remove = [i for i in instances if i.rect.collidepoint(placepos)]
                    for i in to_remove:
                        instances.remove(i)
                    if not to_remove:
                        instances.append(Block(placepos[0],placepos[1],currentbspr))

    for i in instances:
        screen.blit(i.sprite,i.rect)
    if not key[K_q]:
        screen.blit(curspr,placepos)

    screen.blit(menuspr,menurect)

    for item in menuitems:
        screen.blit(item.sprite,item.pos)
        if item.rect.collidepoint(mse):
            if pygame.mouse.get_pressed()==(1,0,0):
                currentbspr=item.sprite
            pygame.draw.rect(screen, ((255,0,0)), item, 1)
    pygame.display.flip()
4

2 回答 2

2

你不能序列化/腌制/搁置 pygame 的Surface对象(至少不是没有很多努力)。所以你的问题的答案是:不要试图序列化你的表面(无论如何它只会浪费磁盘空间)。

例如,您可以创建一个简单dict的来存储您的表面,并让您的类只存储密钥,例如:

menuspr=pygame.image.load('images/menu.png').convert()
b1spr=pygame.image.load('images/b1.png').convert()
b2spr=pygame.image.load('images/b2.png').convert()
currentbspr=b1spr
curspr=pygame.image.load('images/curs.png').convert()
curspr.set_colorkey((0,255,0))
# create a dict to store all surfaces
surf_dict = {'b1spr': b1spr, 
             'b2spr': b2spr, 
             'currentbspr': currentbspr, 
             'curspr': curspr}

...
class Block(object):
    def __init__(self,x,y,spr):
        self.x=x
        self.y=y
        self.sprite=spr
        # self.sprite is no longer a Surface, but a str
        self.rect=surf_dict[self.sprite].get_rect(x=self.x,y=self.y)

...
    ...
        # don't pass the surface to the Block, just the key 
        instances.append(Block(placepos[0],placepos[1], 'currentbspr'))

...
    for i in instances:
        # get the Surface from the dict, not from the instance itself
        screen.blit(surf_dict[i.sprite],i.rect)

现在您可以节省地尝试腌制/搁置所有实例(我看到您在这里Block提出了相关问题)。

于 2013-10-25T12:53:53.387 回答
0

我自己找到了解决方法。我使用python内置的open(fname,mode)来创建一个级别文件。

每当创建一个块时,它都会获取块的精灵名称和坐标,并将其以 .bin 格式添加到保存文件中:

f.write('Block('+str(placepos[0])+','+str(placepos[1])+',b1spr).')

然后我创建了一个函数来读取它,并相应地创建关卡:

def CreateLevel(levelname):
    f=open(levelname,'r')
    obj=f.read()
    f.close()
    obj=obj.split('.')
    for b in obj:
        instances.append(eval(b))

它与飞行的颜色一起使用!

这是整个代码,谢谢大家的帮助。

import pygame
from pygame.locals import *

#initstuff
pygame.init()
screen=pygame.display.set_mode((640,480))
pygame.display.set_caption('PiMaze')
instances=[]
level='save.bin'

#loadsprites
menuspr=pygame.image.load('images/menu.png').convert()
b1spr=pygame.image.load('images/b1.png').convert()
b2spr=pygame.image.load('images/b2.png').convert()
b3spr=pygame.image.load('images/b3.png').convert()
currentbspr=b1spr
curspr=pygame.image.load('images/curs.png').convert()
curspr.set_colorkey((0,255,0))

#menu
menuspr.set_alpha(185)
menurect=menuspr.get_rect(x=-260,y=4)

class MenuItem(object):
    def __init__(self,pos,spr):
        self.x=pos[0]
        self.y=pos[1]
        self.sprite=spr
        self.pos=(self.x,self.y)
        self.rect=self.sprite.get_rect(x=self.x,y=self.y)

class Block(object):
    def __init__(self,x,y,spr):
        self.x=x
        self.y=y
        self.sprite=spr
        self.rect=self.sprite.get_rect(x=self.x,y=self.y)

def CreateLevel(levelname):
    f=open(levelname,'r')
    obj=f.read()
    f.close()
    obj=obj.split('.')
    for b in obj:
        instances.append(eval(b))

try:
    CreateLevel(level)
except:
    pass

f=open(level,'a+')

while True:
    #menu items
    b1menu=b1spr.get_rect(x=menurect.left+32,y=48)
    b2menu=b2spr.get_rect(x=menurect.left+64,y=48)
    b3menu=b3spr.get_rect(x=menurect.left+96,y=48)
    menuitems=[MenuItem(b1menu,b1spr),MenuItem(b2menu,b2spr),MenuItem(b3menu,b3spr)]

    screen.fill((20,30,85))
    mse=pygame.mouse.get_pos()
    key=pygame.key.get_pressed()
    placepos=((mse[0]/16)*16,(mse[1]/16)*16)
    if key[K_q]:
        if mse[0]<260:
            if menurect.right<255:
                menurect.right+=1
        else:
            if menurect.left>-260:
                menurect.left-=1
    else:
        if menurect.left>-260:
            menurect.left-=1
    for e in pygame.event.get():
        if e.type==QUIT:
            f.close()
            exit()

        if menurect.right<100:
            if key[K_LSHIFT]:
                if pygame.mouse.get_pressed()==(1,0,0):
                    to_remove = [i for i in instances if i.rect.collidepoint(placepos)]
                    if not to_remove:
                        instances.append(Block(placepos[0],placepos[1],currentbspr))
                        f.write('Block('+str(placepos[0])+','+str(placepos[1])+',b1spr).')
                    to_remove = []

            if not key[K_LSHIFT] or key[K_RSHIFT]:    
                if e.type==MOUSEBUTTONUP:
                    if e.button==1:
                        to_remove = [i for i in instances if i.rect.collidepoint(placepos)]
                        for i in to_remove:
                            instances.remove(i)
                        if not to_remove:
                            instances.append(Block(placepos[0],placepos[1],currentbspr))
                            f.write('Block('+str(placepos[0])+','+str(placepos[1])+',b1spr).')

            if key[K_RSHIFT]:
                if pygame.mouse.get_pressed()==(1,0,0):
                    to_remove = [i for i in instances if i.rect.collidepoint(placepos)]
                    for i in to_remove:
                                instances.remove(i)
                    to_remove=[]

    for i in instances:
        screen.blit(i.sprite,i.rect)
    if not key[K_q]:
        screen.blit(curspr,placepos)

    screen.blit(menuspr,menurect)

    for item in menuitems:
        screen.blit(item.sprite,item.pos)
        if item.rect.collidepoint(mse):
            if pygame.mouse.get_pressed()==(1,0,0):
                currentbspr=item.sprite
            pygame.draw.rect(screen, ((255,0,0)), item, 1)
    pygame.display.flip()
于 2013-10-25T15:43:04.490 回答