我是Kivy的新人。
我正在写一部经典的生活游戏,还有更多的互动。我的Python代码正在工作,除了泄漏内存!它真的很烦人,因为我只使用相同的双胞胎结构来代替下一代的结果,所以我不指望它会成长!这是我的代码:
import kivy
kivy.require('1.7.2')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import *
from kivy.uix.label import Label
from kivy.clock import Clock
import random
class UnlifeGame(Widget):
colors = {0: [0, 0, 0], 1: [1, .8, .2], 10: [.2, .8, .2]}
testing=0
cells=[]
def on_touch_down(self, touch):
x1st = int((touch.x - 14) / 12)
y1st = int((touch.y - 14) / 12)
for xSquad in range(x1st, x1st + 2):
if xSquad >= len(self.cells):
xSquad = 0
for ySquad in range(y1st, y1st + 2):
if ySquad >= len(self.cells[0]):
ySquad = 0
self.cells[xSquad][ySquad][self.testing] = 10
with self.canvas:
Color(self.colors[10][0], self.colors[10][1], self.colors[10][2])
Rectangle(pos=(12+xSquad*12, 12+ySquad*12), size=(10, 10))
def update(self, dt):
if len(self.cells) == 0:
with self.canvas:
# set to Amber color
Color(1, .8, .2)
for xx in range(0, (self.width-14)/12):
self.cells.append([])
for yy in range(0, (self.height-14)/12):
# Add a cell holder
self.cells[xx].append([int(random.randint(0,2) == 0), 0])
if self.cells[xx][yy][0] == 1:
Rectangle(pos=(12+xx*12, 12+yy*12), size=(10, 10))
return
nextgen = int(self.testing == 0)
for xx in range(0, len(self.cells)):
for yy in range(0, len(self.cells[xx])):
neigh = bool(self.cells[xx][yy][self.testing]) * -1 # Do not count itself!
zombies = 0
for nx in range(xx-1, xx+2):
if nx >= len(self.cells):
nx = 0
for ny in range(yy-1, yy+2):
if ny >= len(self.cells[xx]):
ny = 0
neigh += bool(self.cells[nx][ny][self.testing]);
zombies += int(self.cells[nx][ny][self.testing] / 10)
if neigh < 2 or neigh > 3:
# DEATH
self.cells[xx][yy][nextgen] = 0
elif neigh == 2 and self.cells[xx][yy][self.testing] == 0:
# NO SPAWN
self.cells[xx][yy][nextgen] = 0
elif zombies >= 2:
# UNLIFE
self.cells[xx][yy][nextgen] = 10
else:
# LIFE
self.cells[xx][yy][nextgen] = 1
if self.cells[xx][yy][nextgen] != self.cells[xx][yy][self.testing]:
# Something is changed
with self.canvas:
# set to Green, Amber OR black color
Color(self.colors[self.cells[xx][yy][nextgen]][0], self.colors[self.cells[xx][yy][nextgen]][1], self.colors[self.cells[xx][yy][nextgen]][2])
Rectangle(pos=(12+xx*12, 12+yy*12), size=(10, 10))
self.testing = int(self.testing == 0)
class UnlifeApp(App):
def build(self):
game = UnlifeGame()
Clock.schedule_interval(game.update, 0.5)
return game
if __name__ == '__main__':
UnlifeApp().run()
我可能需要取消设置的唯一对象是我在画布上绘制的Rectangle。但我不确定它会有用,因为我认为它只会被画布绘制并处理掉。但是,如果不是,我怎样才能将过时的那些删除它们到画布中?
我做错了什么?
答案 0 :(得分:3)
你的画布代码非常低效 - 每次游戏改变时,你都会在画布上添加新的Color和Rectangle指令而不删除旧的指令,这样你就可以有效地绘制越来越多的矩形了其他一切。我想这就是你所谓的内存泄漏的原因。
最好只绘制一次所有矩形,但保留对图形对象的引用并更新它们而不是绘制在顶部。这非常有效,无论是在Python中(您只制作所有对象)还是在图形层中(您只需更改现有图形对象的某些参数,而无需添加新的对象进行处理)。
执行此操作的基本方法是
with self.canvas:
self.color = Color(...)
self.rectangle = Rectangle(...)
之后您可以self.color.rgba = [1, 0, 0, 1]
获取红色(或类似于Color
的所有其他属性),或类似self.rectangle.pos = (10, 10)
来更新它。在您的情况下,您不希望单引用,但可以存储所有颜色的引用列表,您所要做的就是更新正确的引用。您根本不需要更改Rectangle
,因为它们的颜色是唯一改变的颜色。