我正在使用画布小部件用python tkinter模块编写一个小游戏。 有一个人,只是一个球,每10秒产生一次炸弹。 炸弹生成3秒后,它开始一个“爆炸”过程,我在self.bomb对象上调用另外4个方法来“动画”它爆炸。
游戏的目的是试图“解除”炸弹。我想出了一些有趣的碰撞检测功能。一旦检测到碰撞,使用以下方法将炸弹从画布上清除:
self.canvas.delete(self.bomb)
然而,即使我已经“解除”了炸弹,下面的炸弹变大和变色(爆炸)的动画仍然会发生。这是因为我原来的炸弹叫:
self.parent.after(3000, self.explode_first)
...我已经链接了3个“爆炸”函数,所有函数都使用.after()方法进行绑定和调用。
我试图通过在.after()中调用的每个方法中插入条件来避免这个问题,就像布尔一样;
if self.bomb # if there's a bomb on the canvas,
self.parent.after(125, self.explode_second) # and explode third and so on
哪个不行。我希望能够“取消”使用after方法创建的tkinter队列的事件,但这里是踢球者。我不能(不能)杀死所有事件,只是画布上的事件。如果可能的话,我还有其他活动要完整保留。
有办法做到这一点吗?如果没有,欢迎提供有关如何在不取消活动后如何执行此操作的反馈和/或建议,并提前致谢!
以下是相关代码,供参考:
def start_game(self):
self.Bombs += 1
self.bombsLabel.configure(text = "Total Bombs: %d" % self.Bombs)
self.b1 = random.randint(1, int(self.canvas.winfo_width()))
self.b2 = random.randint(1, int(self.canvas.winfo_height()))
self.b3 = self.b1 + 20
self.b4 = self.b2 + 20
self.create_bomb()
self.parent.after(10000, self.start_game)
和:
# continuously make and explode bombs
def create_bomb(self):
self.bomb = self.canvas.create_oval(self.b1,
self.b2,
self.b3,
self.b4,
fill = "red")
if self.bomb:
self.parent.after(3000, self.explode_first)
def explode_first(self):
if self.bomb:
self.b1 -= 5
self.b2 -= 5
self.b3 += 5
self.b4 += 5
self.canvas.delete(self.bomb)
self.bomb = self.canvas.create_oval(self.b1,
self.b2,
self.b3,
self.b4,
fill = "orange")
self.parent.after(125, self.explode_second)
def explode_second(self):
if self.bomb:
self.b1 -= 5
self.b2 -= 5
self.b3 += 5
self.b4 += 5
self.canvas.delete(self.bomb)
self.bomb = self.canvas.create_oval(self.b1,
self.b2,
self.b3,
self.b4,
fill = "yellow")
self.parent.after(125, self.explode_third)
def explode_third(self):
self.b1 -= 5
self.b2 -= 5
self.b3 += 5
self.b4 += 5
self.canvas.delete(self.bomb)
self.bomb = self.canvas.create_oval(self.b1,
self.b2,
self.b3,
self.b4,
fill = "white")
self.parent.after(125, self.explode_fourth)
def explode_fourth(self):
self.canvas.delete(self.bomb)
def bomb_disarmed(self):
print "disarmed the bomb!"
self.canvas.delete(self.bomb)
答案 0 :(得分:1)
after
方法返回表示已调度事件的ID。如果您保存了ID,则可以致电after_cancel
取消活动:
self.after_id = self.parent.after(3000, self.explode_first)
...
self.parent.after_cancel(self.after_id)
答案 1 :(得分:0)
您可以向您正在使用的类添加属性:
self.isDisarmed = False
然后将此行添加到bomb_disarmed
:
self.isDisarmed = True
然后在explode_first
中,添加一个测试以查看炸弹是否已经解除武装:
def explode_first(self):
if self.bomb:
if self.isDisarmed:
self.parent.after(125, self.explode_fourth) # If bomb is disarmed, skip to the last step, where the bomb is deleted.
else: # Otherwise, carry on with bomb explosion
self.b1 -= 5
self.b2 -= 5
self.b3 += 5
self.b4 += 5
self.canvas.delete(self.bomb)
self.bomb = self.canvas.create_oval(self.b1,
self.b2,
self.b3,
self.b4,
fill = "orange")
self.parent.after(125, self.explode_second)
作为一般原则,我建议将Bomb
作为一个类,它有自己的内部属性和方法。这样可以更容易地跟踪炸弹发生的事情,结果应该是什么,并且可以做出多个炸弹等事情。
编辑:
Re:从另一个类的方法绘制App
的画布,这是一种方式:
class App:
def __init__(self, ...):
self.canvas = Tkinter.Canvas(...)
self.thingy = SomethingElse()
class SomethingElse:
def __init__(self, parentApp):
self.parentApp = parentApp
def drawSomething(self):
self.parentApp.canvas.create_oval(...)
a = App(...)
s = SomethingElse(a)
s.drawSomething()