我正在尝试使用Tkinter库在python中制作类似破砖机的游戏。我有一个运行良好的代码的先前版本,但由于缩进错误,所有函数都在__init__
。当我更正此错误然后添加功能以使其成为可玩的游戏时,我的主动画循环停止工作。我阅读了其他帖子,显示这是一个间距错误,并验证这不是使用python -tt
。更新:self.moveBall()
已移至__init__
,但moveBall()
仍未运行。
from tkinter import *
class Application(Frame):
def __init__(self):
# Constructing the Screen
root = Tk()
Frame.__init__(self)
self.canvas = Canvas(root, width=800, height=400)
# Label
self.v = StringVar()
self.l = 5
self.label = Label(root, textvariable=self.v, font=('Courier',
20), bg='white', width=50)
self.v.set('Lives: ' + str(self.l))
self.label.grid()
self.canvas.grid()
# Ball
self.canvas.create_oval(
2,
2,
22,
22,
fill='red',
tags='ball',
)
# Paddle
self.canvas.create_rectangle(
360,
380,
440,
400,
fill='black',
tag='paddle',
)
# Keybindings
self.canvas.focus_set()
self.canvas.bind('<Left>', self.paddleLeft)
self.canvas.bind('a', self.paddleLeft)
self.canvas.bind('<Button-1>', self.paddleLeft)
self.canvas.bind('<Right>', self.paddleRight)
self.canvas.bind('d', self.paddleRight)
self.canvas.bind('<Button-3>', self.paddleRight)
# Logic
self.horizontal_direction = 'east'
self.vertical_direcction = 'south'
self.moveBall()
def collide(self):
(x1, y1, x2, y2) = self.canvas.coords('ball')
(px1, py1, px2, py2) = self.canvas.coords('paddle')
if x2 >= 800:
self.horizontal_direction = 'west'
if x1 <= 0:
self.horizontal_direction = 'east'
if y1 <= 0:
self.vertical_direcction = 'south'
if y2 >= 400:
self.l -= 1
self.v.set('Lives: ' + str(self.l))
self.vertical_direcction = 'north'
if y2 >= py1:
if x1 in range(int(px1), int(px2)) or x2 in range(int(px1),
int(px2)):
self.vertical_direcction = 'north'
def moveBall(self):
while True:
if self.horizontal_direction == 'east':
self.canvas.move('ball', 2, 0)
else:
self.canvas.move('ball', -2, 0)
if self.vertical_direcction == 'south':
self.canvas.move('ball', 0, 2)
else:
self.canvas.move('ball', 0, -2)
self.canvas.after(15)
self.collide()
self.canvas.update()
def paddleLeft(self, event):
(px1, py1, px2, py2) = self.canvas.coords('paddle')
if px1 >= 0:
self.canvas.move('paddle', -5, 0)
self.canvas.after(15)
self.canvas.update()
def paddleRight(self, event):
(px1, py1, px2, py2) = self.canvas.coords('paddle')
if px2 <= 800:
self.canvas.move('paddle', 5, 0)
self.canvas.after(15)
self.canvas.update()
def main():
app = Application()
app.mainloop()
main()
这是控制台输出:
Traceback (most recent call last):
File "C:\Users\daeda\Downloads\main.py", line 4, in <module>
class Application(Frame):
File "C:\Users\daeda\Downloads\main.py", line 107, in Application
self.moveBall()
NameError: name 'self' is not defined
答案 0 :(得分:1)
据我所知,当您尝试使用self
从类外部调用方法时,通常会发生此类错误。
我相信你的错误在于
self.moveball()
在这里,您尝试从课程范围之外的moveball()
拨打self
。
我希望它能帮助你克服这个问题。
答案 1 :(得分:0)
我做了这样的事情:
它使用self.root
,因此我可以在moveBall
中使用self.root.after(15, moveBall)
并在15ms后再次运行moveBall
并且我不需要while True
。我也不需要canvas.after(15)
和canvas.update()
。
我从Frame
删除了class Application(Frame):
,因为您将所有小部件直接添加到root
,并且从未使用此Frame
。在小部件中,您必须使用self
代替root
向此Frame
添加小部件,而Frame
必须使用master=root
将小部件添加到主窗口
from tkinter import *
class Application():
def __init__(self):
# Constructing the Screen
self.root = Tk()
self.canvas = Canvas(self.root, width=800, height=400)
# Label
self.v = StringVar()
self.l = 5
self.label = Label(self.root, textvariable=self.v, font=('Courier',
20), bg='white', width=50)
self.v.set('Lives: ' + str(self.l))
self.label.grid()
self.canvas.grid()
# Ball
self.canvas.create_oval(
2,
2,
22,
22,
fill='red',
tags='ball',
)
# Paddle
self.canvas.create_rectangle(
360,
380,
440,
400,
fill='black',
tag='paddle',
)
# Keybindings
self.canvas.focus_set()
self.canvas.bind('<Left>', self.paddleLeft)
self.canvas.bind('a', self.paddleLeft)
self.canvas.bind('<Button-1>', self.paddleLeft)
self.canvas.bind('<Right>', self.paddleRight)
self.canvas.bind('d', self.paddleRight)
self.canvas.bind('<Button-3>', self.paddleRight)
# Logic
self.horizontal_direction = 'east'
self.vertical_direcction = 'south'
# run after 250ms so mainloop has time to start
self.root.after(250, self.moveBall)
self.root.mainloop()
def collide(self):
(x1, y1, x2, y2) = self.canvas.coords('ball')
(px1, py1, px2, py2) = self.canvas.coords('paddle')
if x2 >= 800:
self.horizontal_direction = 'west'
if x1 <= 0:
self.horizontal_direction = 'east'
if y1 <= 0:
self.vertical_direcction = 'south'
if y2 >= 400:
self.l -= 1
self.v.set('Lives: ' + str(self.l))
self.vertical_direcction = 'north'
if y2 >= py1:
if x1 in range(int(px1), int(px2)) or x2 in range(int(px1),
int(px2)):
self.vertical_direcction = 'north'
def moveBall(self):
if self.horizontal_direction == 'east':
self.canvas.move('ball', 2, 0)
else:
self.canvas.move('ball', -2, 0)
if self.vertical_direcction == 'south':
self.canvas.move('ball', 0, 2)
else:
self.canvas.move('ball', 0, -2)
self.collide()
# run again after 15ms - so I don't need `while True`
self.root.after(15, self.moveBall)
def paddleLeft(self, event):
(px1, py1, px2, py2) = self.canvas.coords('paddle')
if px1 >= 0:
self.canvas.move('paddle', -5, 0)
def paddleRight(self, event):
(px1, py1, px2, py2) = self.canvas.coords('paddle')
if px2 <= 800:
self.canvas.move('paddle', 5, 0)
# --- start ---
Application()