This is my first post. I started coding, considering a career exchange two months ago, and am working on a Tetris clone. I have implemented most of the basic functions, but I can not get the game to be constantly updated with the after loop.
I use Tkinter to create my own Gui and try to set up event-oriented programming.
I understand that after(Time, Event) from Tkinter should plan that the Event callback function will occur after the delay specified by Time . I think that after this, the code should continue to execute subsequent elements.
The frame update function ( game.updateBoard() ) performs most of the necessary events for tetris to work, and then calls itself after. I call it once when initializing a game instance.
Instead of going to mainloop() , the game.updateBoard() function calls itself through after indefinitely.
I suspect that it does not behave the way I thought that after works, which will continue to execute the script until the specified delay occurs. I think he is waiting for the callback to complete to continue.
I tried to find the resource, but could not.
If you have any suggestions for resolving this issue, the attached code, or for coding in general, I am very glad to hear them! This is an educational process, and I will be happy to try everything that you offer.
Here is the relevant piece of code:
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()