无限循环"after":从不进入主循环



这是我的第一篇文章。两个月前,当我考虑转行时,我开始编码,现在正在制作一个俄罗斯方块克隆。我已经实现了大部分核心功能,但无法通过后循环不断刷新游戏。

我正在使用Tkinter制作我的Gui,并尝试面向事件的编程。

我的理解是,来自Tkinterafter(Time, Event)应该调度Event回调函数在Time指定的延迟之后发生的任何事情。我认为代码应该在这之后继续执行后续项目。

我的帧刷新函数(game.updateBoard())完成俄罗斯方块工作所需的大多数事件,然后使用after调用自己。我在初始化游戏实例时调用过一次。

game.updateboard()函数不是继续执行mainloop(),而是无限期地通过after调用自己。

我怀疑它的行为与我认为after的工作方式不同,即继续执行脚本,直到出现指定的延迟。我认为它正在等待回调终止以继续。

我试着找到这方面的资源,但找不到。

如果你对解决这个问题、所附代码或一般编码有建议,我很高兴听到!这是一个学习的过程,我很乐意尝试你提出的任何建议。

以下是代码的相关部分:

class game():
    def __init__(self): #Set up board and image board
        self.pieces = ["L","J","S","Z","T","O","I"]
        self.board = boardFrame()
        self.root = Tk()
        self.root.title("Tetris")
        self.root.geometry("250x525")
        self.frame = Frame(self.root)
        #set up black and green squares for display
        self.bSquare = "bsquare.gif"
        self.gSquare = "square.gif"
        self.rSquare = "rsquare.gif"
        self.image0 = PhotoImage(file = self.bSquare)
        self.image1 = PhotoImage(file = self.gSquare)
        self.image2 = PhotoImage(file = self.rSquare)
        #get an initial piece to work with
        self.activeBlock = piece(self.pieces[random.randint(0,6)])
        #Tells program to lower block every half second
        self.blockTimer = 0
        self.updateBoard()
        self.root.bind('<KeyPress-Up>', self.turn)
        self.root.bind('<KeyPress-Right>', self.moveR)
        self.root.bind('<KeyPress-Left>', self.moveL)
        self.root.bind('<KeyPress-Down>',self.moveD)
        print("Entering mainloop")
        self.root.mainloop()
    def turn(self, event):
        self.activeBlock.deOccupy(self.board)
        self.activeBlock.turn()
        self.activeBlock.occupy(self.board)
        self.drawGrid(self.board.grid)
    def moveR(self, event):
        self.activeBlock.deOccupy(self.board)
        self.activeBlock.updatePos([1,0], self.board)
        self.activeBlock.occupy(self.board)
        self.drawGrid(self.board.grid)
    def moveL(self, event):
      if self.activeBlock.checkLeft(self.board) == False:
        self.activeBlock.deOccupy(self.board)
        self.activeBlock.updatePos([-1,0], self.board)
        self.activeBlock.occupy(self.board)
        self.drawGrid(self.board.grid)
    def moveD(self, event): #find
        self.activeBlock.deOccupy(self.board)
        self.activeBlock.updatePos([0,-1],self.board)
        if self.activeBlock.checkBottom(self.board) == True:
            self.activeBlock.occupy(self.board)
            self.activeBlock = piece(self.pieces[random.randint(0,6)])
##            self.activeBlock = piece(self.pieces[1])
            print("bottomed")
            self.activeBlock.occupy(self.board)
        self.activeBlock.occupy(self.board)
        self.drawGrid(self.board.grid)
    def drawGrid(self, dGrid):
        #Generate squares to match tetris board
        for widget in self.frame.children.values():
            widget.destroy()
        self.activeBlock.occupy(self.board)
        for x in range(9,-1,-1):
            for y in range(20,-1,-1):
                if self.board.grid[x][y] == 1:
                    self.frame.displayA = Label(self.frame, image=self.image1)
##                    self.frame.displayA.image = self.image1
                    self.frame.displayA.grid(row=21-y, column=x)

                else:
                    self.frame.displayA = Label(self.frame, image = self.image0)
##                    self.frame.displayA.image = self.image0
                    self.frame.displayA.grid(row=21-y, column=x)
        self.frame.displayA = Label(self.frame, image = self.image2)
        self.frame.displayA.grid(row = 21 - self.activeBlock.center[1], column = self.activeBlock.center[0])
        self.frame.grid()
    def updateBoard(self):
        self.blockTimer += 1
        "print updateBoard Loop"
        ## 1)check for keyboard commands
        #1.1 move block by keyboard commands
        #2) see if block has bottomed out, if it has, have it enter itself into the grid and generate a new block.
        if self.activeBlock.checkBottom(self.board) == True:
            self.activeBlock.occupy(self.board)
            self.activeBlock = piece(self.pieces[random.randint(0,6)])
            print("bottomed")
            self.activeBlock.occupy(self.board)
        #2.2 - if block has not bottomed and 50 frames (~.5 seconds) have passed, move the active block down a square after clearing its old space. 
        elif self.blockTimer%12 == 0:
            self.activeBlock.deOccupy(self.board)
            self.activeBlock.updatePos([0,-1], self.board)
            self.activeBlock.occupy(self.board)

    ## 4) check for filled rows
        for y in range(1,21):
            for x in range(10):
                rowFull = True
                if self.board.grid[x][y] == 0:
                    rowFull == False  
            #4.1 if any row is filled, delete it and then move all rows above the deleted row down by one
            if rowFull == True:
                for x2 in range(10):
                    self.board.grid[x2][y] = 0
                    for y2 in range(y+1,21):
                        if self.board.grid[x2][y2] == 1:
                            self.board.grid[x2][y2] = 0
                            self.board.grid[x2][y2-1] = 1
            #4.11 if the row is full and the row above it was full, delete the row again as well as the row above it, and move all rows down by 2
                for x in range(10):
                    rowFull = True
                    if self.board.grid[x][y] == 0:
                        rowFull == False
                        if rowFull == True:
                            for x2 in range(10):
                                try:
                                    self.board.grid[x2][y] = 0
                                    self.board.grid[x2][y+1] = 0
                                except:
                                    pass
                                for y2 in range(y+2,21):
                                    try:
                                        if self.board.grid[x2][y2] == 1:
                                            self.board.grid[x2][y2] = 0
                                            self.board.grid[x2][y2-2] = 1
                                    except:
                                        pass

        #5) if there is a block in the top row, end the game loop
        for x in range(10):
            if self.board.grid[x][20] == 1:
                game = "over"

        #6) update image
        self.activeBlock.occupy(self.board)
        self.drawGrid(self.board.grid)
        self.frame.after(500, self.updateBoard())

Game = game()

您想要执行self.frame.after(500, self.updateBoard)

这里的区别是微妙的(self.updateBoard而不是self.updateBoard())。在您的版本中,您将函数的结果传递给after方法,而不是传递函数

相关内容

  • 没有找到相关文章

最新更新