2013-10-25 85 views
0

我正在製作一款遊戲,您可以在其中創建迷宮。你可以在16x16的網格上放置塊,同時從各種塊中進行選擇以使其成爲關卡。當你創建一個塊,它增加了這個類:Pygame:保存對象/類/表面列表

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

回答

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) 

現在你可以savely嘗試泡菜/擱置所有Block -instances(我看到你問了一個相關的問題here)。

0

我自己找到了解決方法。我使用建立在open(fname,mode)中的python來創建一個關卡文件。

只要創建一個塊,它採用精靈的名稱和分塊的座標,並把它添加到保存文件中的.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()