2013-06-11 32 views
1

我一直在创建一个简单的基于磁贴的游戏来帮助我学习python和wx python。对于初学者,我想创建自己的“世界”并测试我制作的简单地图生成器,然后绑定返回键以生成新地图并显示它。 那是当我遇到这个问题。每次你点击return时,它会变慢很多,逐行渲染每个tile(这显然很慢并且效率低下),最终只会冻结。wxPython渲染问题,非常缓慢和崩溃,不知道为什么

我是一个相当新手的程序员,从来没有处理任何形式的GUI,所以这对我来说都是非常新的,请耐心等待我!我可以猜测,我设置的东西对机器来说是非常重要的,也许我正在引起很多递归。我根本不知道。另外我对OOP并不太熟悉,所以我只是按照示例创建我的类(因此为什么我只有1个大型类处理所有内容,我不太清楚所有'__ something__'函数。)

Here在所有到目前为止,我写的代码,请忽略注释的部分,他们是未来的职能等:

import wx 
import random 


#main screen class, handles all events within the main screen 
class MainScreen(wx.Frame): 

    hMap = [] 
    tTotalX = 50 
    tTotalY = 50 

    def __init__(self, *args, **kwargs): 
     #This line is equivilant to wx.Frame.__init__('stuff') 
     super(MainScreen, self).__init__(None, -1, 'You shouldnt see this', style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX) 

     self.renderScreen() 

    def genMap(self,tTotalX,tTotalY): 
     count1 = 0 
     count2 = 0 
     self.hMap = [] 
     while count1 < tTotalY: 
      count2 = 0 
      newrow = [] 
      while count2 < tTotalX: 
       newrow.append(random.randint(1,120)) 
       count2 += 1 
      self.hMap.append(newrow) 
      count1 += 1 
     self.smooth(tTotalX, tTotalY) 
     self.smooth(tTotalX, tTotalY) 


    def smooth(self, tTotalX, tTotalY): 
     countx = 0 
     county = 0 
     while county < tTotalY: 
      countx = 0 

      while countx < tTotalX: 
       above = county - 1 
       below = int(county + 1) 
       east = int(countx + 1) 
       west = int(countx - 1) 
       if east >= tTotalX: 
        east = 0 
       if west < 0: 
        west = tTotalX -1 

       teast = self.hMap[county][east] 
       twest = self.hMap[county][west] 

       if above < 0 or below >= tTotalY: 
        smooth = (self.hMap[county][countx] + teast + twest)/3 
       else: 
        tabove = self.hMap[above][countx] 
        tbelow = self.hMap[below][countx] 
        smooth = (self.hMap[county][countx] + tabove + tbelow + teast + twest)/5 

       self.hMap[countx][county] = int(smooth)    
       countx += 1 

      county += 1   

    def getTileType(self, coordX, coordY, totalX, totalY): 
     #this is the part of map creation, getting tile type based on tile attributes 
     tType = '' 
     height = self.hMap[coordX][coordY] 
     #the below values are all up to tweaking in order to produce the best maps 
     if height <= 55: 
      tType = 'ocean.png' 

     if height > 55: 
      tType = 'coast.png' 

     if height > 60: 
      tType = 'grassland.png' 

     if height > 75: 
      tType = 'hills.png' 

     if height > 80: 
      tType = 'mountain.png' 

     if tType == '': 
      tType = 'grassland.png' 

     return tType 

    #render the main screen so that it dislays all data 
    def renderScreen(self): 
     frameSize = 810 #Size of the game window 
     tTotalX = self.tTotalX #the dimensions of the tile display, setting for in-game coordinates 
     tTotalY = self.tTotalY 
     #tsTiny = 1 #ts = Tile Size 
     #tsSmall = 4 
     tsMed = 16 
     #tsLrg = 32 
     #tsXlrg = 64 
     tsCurrent = tsMed #the currently selected zoom level, for now fixed at tsMed 
     pposX = 0 #ppos = Pixel Position 
     pposY = 0 
     tposX = 0 #tpos = tile position, essentially the tile co-ordinates independent of pixel position 
     tposY = 0 
    #The below is just an example of how to map out the grid, it should be in its own function in due time 

     self.genMap(tTotalX, tTotalY) 

     while tposY < tTotalY: #loops through all y coordinates 
      tposX = 0 
      while tposX < tTotalX: #loops through all x coordinates 
       pposX = tposX*tsCurrent 
       pposY = tposY*tsCurrent 
       tiletype = self.getTileType(tposX,tposY,tTotalX,tTotalY) 

       img = wx.Image(('F:\First Pass\\' + str(tiletype)), wx.BITMAP_TYPE_ANY).ConvertToBitmap() 
       wx.StaticBitmap(self, -1, img, (pposX, pposY))#paints the image object (i think) 

       tposX += 1 
      tposY += 1 

     self.Bind(wx.EVT_KEY_DOWN, self.onclick) 
     self.SetSize((frameSize-4, frameSize+16)) 
     self.SetBackgroundColour('CYAN') 
     self.Centre() 
     self.SetTitle('Nations First Pass') 
     #string = wx.StaticText(self, label = 'Welcome to Nations, First Pass', pos = (tTotalX*tsCurrent/2,tsCurrent*tTotalY/2)) 
     #string.SetFont(wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)) 

     self.Show() 

    def onclick(self, e): 
     key = e.GetKeyCode() 

     if key == wx.WXK_RETURN: 

      self.renderScreen() 


#game loop 
    def main(): 
     app = wx.App() 
     MainScreen(None) 
     app.MainLoop() 

if __name__ == '__main__': 
    main() 

您需要制作你自己的“ocean.png”“coast.png”“草原.png''hills.png'和'mountain.png'(它们需要为16x16像素),或者您可以使用我的Imgur链接:

http://imgur.com/a/uFxfn

另请根据需要更改img代码中的文件路径。我需要弄清楚如何设置它自己做,但这又是另一个挑战。

如果您对此有任何了解,我会非常感激。

回答

0

每次调用renderScreen时,都会创建一组新的wx.StaticBitmaps,并且在创建新集之前不会删除它们。过了一段时间,你将会看到堆叠在一起的小部件不再可见,但仍然会消耗资源。至少你应该改变你的程序,使得你的程序只有一组wx.StaticBitmaps,跟踪它们,然后当你想改变它们时调用它们的SetBitmap方法。

为了获得更好的性能,您应该忘记StaticBitmaps并在EVT_PAINT处理程序中自己绘制图像。 StaticBitmaps旨在“静态”,IOW不会变化太大。相反,您可以为该窗口实现一个EVT_PAINT处理程序,并且每当需要重绘窗口时都会调用该处理程序,并且只需调用窗口的Refresh方法即可触发新的重绘。

+0

谢谢我会给它一个 – Bellaby

+0

现在它的工作非常感谢! – Bellaby