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 を返します。after_cancelID を保存すると、呼び出してイベントをキャンセルできます。

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独自の内部属性とメソッドを持つクラスを作成することをお勧めします。これにより、爆弾に何が起こっているのか、結果がどうあるべきかを追跡しやすくなり、複数の爆弾を持つなどのことが可能になります。

編集:

AppRe:別のクラスのメソッドから のキャンバスに描画する方法の 1 つは次のとおりです。

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 に答える