在Toplevel窗口处于活动状态时(直到其被破坏)暂停动画循环?

时间:2015-06-19 14:55:51

标签: python animation tkinter

我有一个乒乓球比赛(改编)。 每次玩家的球拍都错过了球,我想要一个窗口出现问题。如果他正确回答,Toplevel窗口应该被销毁并且用户可以继续游戏,失败将导致更多问题直到用户正确 - 然后他们可以继续游戏。

如何在Toplevel窗口处于活动状态时暂停动画循环,如何在Toplevel窗口被销毁时取消暂停动画循环?

要处理的代码的主要焦点是Paddle类的第一个类(questions_window),game_flow函数和paddle_collisions方法。

以下是所有代码:

from tkinter import *
import time

#starting velocity for the ball
x_speed = 25
y_speed = 25

class questions_window():
    def __init__(self, master):
        self.master = master
        self.master.geometry("300x300")
        self.master.title("Questions")

    def focus(self):
        self.master.attributes("-topmost", 1)
        self.master.grab_set()

class table():
    '''This is the table class - the background for the game and it's drawings'''
    def __init__ (self, window, colour = 'green', width=600, height = 400, score1 = 0, score2 = 0):
        self. colour = colour
        self.width = width
        self.height = height
        self.canvas = Canvas(window, bg=self.colour, height=self.height, width=self.width)
        self.canvas.pack()
        self.canvas.create_line(300, 0, 300, 400, fill="red")
        self.score1 = score1
        self.score2 = score2

    #this receives the coordinates of the ball and draws an oval based on these coordinates
    #the instance of this item is returned to the ball class' 'circle' attribute
    def draw_oval(self, oval):
        x1 = oval.x_posn
        x2 = oval.x_posn + oval.width
        y1 = oval.y_posn
        y2 = oval.y_posn + oval.height
        c = oval.colour
        return self.canvas.create_oval(x1, y1, x2, y2, fill=c)

    #this recieves the coordinates of the paddle and draws a rectangle based on these coordinates
    #the instance of this item is returned to the paddle class' 'rectangle' attribute
    def draw_rectangle(self, rectangle):
        x1 = rectangle.x_posn
        x2 = rectangle.x_posn + rectangle.width
        y1 = rectangle.y_posn
        y2 = rectangle.y_posn + rectangle.height
        c = rectangle.colour
        return self.canvas.create_rectangle(x1, y1, x2, y2, fill=c)

    #this method creates text on the canvas (the scores separated with a dash)
    def reset_scorecard(self):
        scores = str(self.score1) + " - " + str(self.score2)
        self.scorecard = self.canvas.create_text(300, 50, font=("Purisa",40), text=scores)

    #this finds out who has won a point and updates the scores on the canvas
    def update_scorecard(self, player):
        if player == 1:
            self.score1 = self.score1 + 1
        elif player == 2:
            self.score2 = self.score2 + 1
        scores = str(self.score1) + " - " + str(self.score2)
        self.canvas.itemconfig(self.scorecard, text=scores)

    #this method, when called, recieves a drawing object and updates its position on the canvas
    def move_item(self, item, x1, y1, x2, y2):
        self.canvas.coords(item, x1, y1, x2, y2)

class ball():
    '''This is the ball class'''
    def __init__(self, table, colour = 'red', width = 25, height = 25, x_speed = 15,
                                                 y_speed = 15, x_start = 5, y_start = 5):
        self.colour = colour
        self.width = width
        self.height = height
        self.x_posn = x_start
        self.y_posn = y_start
        self.table = table
        self.x_start = x_start
        self.y_start = y_start
        self.x_speed = x_speed
        self.y_speed = y_speed
        self.circle = self.table.draw_oval(self)

    #this method updates the ball's x and y coordinates by the speed values
    #it then checks if the ball has hit any walls - if it has it
    #reverses the x or y speeds depending on the wall it has hit
    #it then moves the item to the new coordinates
    def move_next(self):
        self.x_posn = self.x_posn + self.x_speed
        self.y_posn = self.y_posn + self.y_speed
        if (self.x_posn <=3):
            self.x_posn = 3
            self.x_speed = -self.x_speed
        if(self.x_posn >= (self.table.width - (self.width - 3))):
            self.x_posn = (self.table.width - (self.width - 3))
            self.x_speed = -self.x_speed
        if (self.y_posn <=3):
            self.y_posn = 3
            self.y_speed = -self.y_speed
        if(self.y_posn >= (self.table.height - (self.height - 3))):
            self.y_posn = (self.table.height - (self.height - 3))
            self.y_speed = -self.y_speed
        x1 = self.x_posn
        x2 = self.x_posn + self.width
        y1 = self.y_posn
        y2 = self.y_posn + self.height
        self.table.move_item(self.circle, x1, y1, x2, y2)

class paddle():
    '''This is the ball class'''
    def __init__(self, master, table, colour = 'blue', width = 10, height = 110,
                                                  x_start = 0, y_start = 20):
        self.colour = colour
        self.width = width
        self.height = height
        self.x_posn = x_start
        self.y_posn = y_start
        self.table = table
        self.master = master
        self.x_start = x_start
        self.y_start = y_start
        self.rectangle = self.table.draw_rectangle(self)

    #this method updates the paddles position on the screen
    #it recieves the mouse' x and y positions and updates the y position
    #of the paddle to match the y position of the mouse
    #it then moves the paddle to the new coordinates
    def move(self, event):
        self.y_posn = event.y
        x1 = self.x_posn
        x2 = self.x_posn + self.width
        y1 = self.y_posn
        y2 = self.y_posn + self.height
        self.table.move_item(self.rectangle, x1, y1, x2, y2)

    #this method checks if the ball has moved passed the paddle
    #if it has it will update the scorecard passing in the value of 2
    #if it has BUT has done so between the top and bottom ends of the paddle
    #it takes this as a paddle hit and updates score with 1 passed to the method
    def paddle_collision(self, ball, master):
        global switch_value
        if ((self.x_posn + self.width) > ball.x_posn) and (self.y_posn < ball.y_posn < (self.y_posn + self.height)):
            ball.x_speed = abs(ball.x_speed)
            print("Yes!")
            self.table.update_scorecard(1)
        elif (self.x_posn+4) > ball.x_posn:
            print("Collision")
            self.table.update_scorecard(2)
            question_win = Toplevel(self.master)
            question_window = questions_window(question_win)
            question_window.focus()

#create the window object
window = Tk()
window.title("Tennis")

#create the table, ball and paddle objects
myTable = table(window)
myTable.reset_scorecard()
myBall = ball(table=myTable, x_speed = x_speed, y_speed = y_speed)
paddle1 = paddle(table=myTable, master = window)

#this is the animation loop which calls itself after every 40ms
#each call calls the ball objects move_next method and the paddle's collision method
def game_flow():
    myBall.move_next()
    paddle1.paddle_collision(myBall,window)
    window.after(40, game_flow)

#first call of game_flow to start game
game_flow()

#binds the mouse events to the padde's move method
window.bind("<Motion>", paddle1.move)

window.mainloop()

1 个答案:

答案 0 :(得分:1)

当您希望动画停止时设置标志,然后随时重新启动动画。

def game_flow():
    if not paused:
        myBall.move_next()
        paddle1.paddle_collision(myBall,window)
        window.after(40, game_flow)

def pause():
    global paused
    paused = True