"nach" looping auf unbestimmte Zeit: noch nie betreten mainloop
Dies ist mein Erster Beitrag. Ich begann das Programmieren, wenn man eine Karriere swap zwei Monaten und arbeite an einem Tetris-Klon. Ich habe implementiert die wichtigsten Funktionen, kann aber nicht bekommen, das Spiel zu aktualisieren kontinuierlich mit einer nach Schleife.
Ich bin mit Tkinter zu produzieren meine Gui und versuche aus Ereignis-orientierten Programmierung.
Mein Verständnis ist, dass after(Time, Event)
aus Tkinter
einplanen sollten, was die Event
callback-Funktion erfolgt nach einer Verzögerung angegeben Time
. Ich denke, dass der code soll weiterhin die Ausführung der Elemente nach dieser.
Meine frame-refresh-Funktion (game.updateBoard()
) übernimmt die meisten der notwendigen Ereignisse für tetris zu arbeiten, dann ruft sich selbst mit nach. Ich nenne es einmal, bei der Initialisierung einer Instanz des Spiels.
Anstelle des Verfahrens zu mainloop()
, die game.updateboard()
Funktion ruft sich selbst über after
auf unbestimmte Zeit.
Vermute ich, dass es sich nicht verhält, wie ich dachte after
gearbeitet, wäre auch weiterhin um das Skript auszuführen, bis die angegebene Verzögerung Auftritt. Ich denke, es ist warten auf den Rückruf zu kündigen, um fortzufahren.
Versuchte ich zu finden, eine Ressource zu diesem Thema, aber konnte nicht.
Wenn Sie Vorschläge für die Festsetzung dieser Frage, die angefügten code, oder für die Kodierung im Allgemeinen, ich bin sehr glücklich, Sie zu hören! Dies ist ein Lernprozess, und ich werde gerne versuchen, so ziemlich alles, was Sie vorschlagen.
Hier ist der relevante Teil des Codes:
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()
- Tim: vergessen Sie nicht zu akzeptieren @mgilson Antwort als "korrekt".
- Dank für die Köpfe oben js. Ich wusste nicht, dass es das war, was ich tun sollte.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wollen Sie tun
self.frame.after(500, self.updateBoard)
.Hier der Unterschied ist subtil, (
self.updateBoard
stattself.updateBoard()
). In Ihrer version, Sie sind vorbei die Ergebnis Ihrer Funktion derafter
Methode statt der übergabe der Funktion. Diese Ergebnisse in die unendliche Rekursion, die du beschrieben hast.self.updateBoard
ist nur eine Referenz auf das Funktionsobjekt. Es ist wichtig zu erkennen, dass der python-Funktionen sind Objekte wie alles andere. Tkinter istafter
Methode nimmt einen reference, um die Funktion und ruft dann, dass die Referenz für die Sie nach der angegebenen Zeit.after
als das 3., 4., &c. Argumente. ZBafter(100, callback, arg1, arg2, arg3, ...)
Finden Sie unter Effbot oder New Mexico Techafter(100,lambda: callback(arg1,arg2,...))
. Ihre version ist wohl besser, obwohl-ich habe nur immer am Ende mit einem Millionen-lambdas bei der Programmierung mit Tkinter.