2013-10-07 50 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看作物理引擎,如果你创作有兴趣的游戏。

相关问题