2013-10-07 86 views
0

我正在搞亂Kivy,並試圖讓某些類似2D網格的應用程序獲得一些遊戲。在我的設計中,每個單元格的網格應該有自己的圖形表示,具體取決於裏面的內容。 下面是我目前簡單的代碼,它只是創建網格並在每個單元格中插入一些圖像。加載同一圖像的多個實例的最佳方式

class MyWidget(Widget): 
    def __init__(self,images,*args, **kwargs): 
     super(MyWidget, self).__init__(*args, **kwargs) 
     self.images = [] 
     for img in images: 
      self.add_image(img) 
     self.bind(pos=self.callback,size=self.callback) 
    def add_image(self,image): 
     self.images.append(Image(source=image,allow_stretch = True,keep_ratio = False)) 
     self.add_widget(self.images[-1]) 
    def callback(self,instance,value): 
     for image in instance.images: 
      image.pos = instance.pos 
      image.size = instance.size 

class StartScreen(Screen): 
    def __init__(self,**kwargs): 
     super(StartScreen, self).__init__(**kwargs) 
     i = 10 
     self.layout = GridLayout(cols=i) 
     self.add_widget(self.layout) 
     for i in range(i*i): 
      self.layout.add_widget(MyWidget(['./images/grass.png','./images/bug1.png'])) 

class TestApp(App): 
    def build(self): 
     return StartScreen() 

的問題是,雖然所有圖像都是一樣的,大公都加載到內存中再次針對每個小區的從我所看到的。它效率不高,特別是當有10000個單元左右時。 我試圖將相同的圖像添加到每個單元格,但事實證明,每個部件只能有一個父級。 我也嘗試初始化一個已經初始化的紋理的新圖像,但是沒有改進。 我嘗試獲取加載圖像的紋理,然後用它作爲紋理創建矩形。事情是這樣的:

def add_image(self,texture): 
    with self.canvas: 
     rect = Rectangle(texture=texture,pos=self.pos, size=self.size) 
     self.rects.append(rect) 

其中質地:

Image(source='./images/grass.png',allow_stretch = True,keep_ratio = False).texture 

它提高了內存使用量(從430MB到160MB爲10000個細胞200kB的圖像,但仍,這是相當多的兩幅圖像。 :)

我的問題:是否有更有效的方式來創建2D網格與許多重複的圖像,在基維? 也許我的解決問題的方法是有缺陷的 - 我在創造遊戲真的沒有expirence ...

+1

我不完全確定,但你可能想試試['Atlas'](http://kivy.org/docs/api-kivy.atlas.html)。這意味着通過加載一個鏡像而不是2個來減少對服務器或硬盤驅動器的調用量。不過,我很想去想可能還有一些內存管理。不完全確定,但值得一試。 –

回答

1

您所看到的內存問題是從你的部件不從紋理管理不善,在kivy紋理將使用kivy內部cache緩存機制,因此如果您嘗試在一分鐘內加載100次圖像,kivy將只重新使用緩存中的現有紋理。

該緩存在設定的時間後會超時,並且會在超時後從磁盤重新加載。由於這個原因,Image小部件有一個reload方法和nocache屬性可以設置。您可以設置手動緩存::

from kivy.cache import Cache 
Cache._categories['kv.image']['limit'] = 0 
Cache._categories['kv.texture']['limit'] = 0 

對於遊戲雖然每個人都應該嘗試使用Atlas,它的緩存中沒有超時,整個機制是朝着使您更好的性能和結構管理爲目標。其他優點包括上傳到GPU的單個紋理=上傳時間的巨大改進,從磁盤讀取時間大大減少。

無論多麼微不足道的開銷以及處理同一Widget的10,000多次迭代時,每個Widget都是如此。你一定會得到內存使用問題。小部件不適合這種用法。你應該看看使用重複紋理, 操縱紋理座標,直接繪製到畫布上,而不使用小部件。喜歡的東西(未經測試)::

texture = Image('grid.jpg').texture 
texture.wrap = 'repeat' 
texture.uvsize = (20, 20) 
with self.canvas: 
    Color(1, 1, 1) 
    Rectangle(pos=(0, 0), size=(2000, 2000), texture=texture) 

,你可能覺得KivEnt和cymunk看作物理引擎,如果你創作有興趣的遊戲。

相關問題