0

我正在使用画布小部件使用 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)
4

2 回答 2

1

after方法返回一个表示预定事件的 id。如果保存id,可以调用after_cancel取消事件:

self.after_id = self.parent.after(3000, self.explode_first)
...
self.parent.after_cancel(self.after_id)
于 2013-10-20T12:33:08.363 回答
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一个类,它有自己的内部属性和方法。这将使跟踪炸弹发生的情况以及结果应该变得更容易,并且可以执行诸如拥有多个炸弹之类的事情。

编辑:

回复: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()
于 2013-10-20T02:59:37.970 回答