我一直在努力将使用CodeSkulptor为在线Python类构建的游戏“ Pong”的版本转换为使用Tkinter的“桌面” Python脚本,以此来教自己如何使用Tkinter 。我已经设法使整个游戏正常运行,除了左(玩家1)球拍。我认为我的按键绑定正确无误,因为正确的(玩家2)拨片可以按预期工作,因为当您按住“向上”或“向下”箭头键时,拨片将移动,直到其达到上下限为止画布,或者在释放任一键时停止。我将按键传递给keydown和keyup处理程序,在这里检查是否按下/释放了哪个键,并采取相应的措施。让我感到困惑的是,如果我将左拨片的移动映射到不同的键(例如,说“ a”或“ d”,或“ Up”或“ Down”箭头),它会按预期工作,但拒绝当我映射了“ w”和“ s”键时可以工作。有谁知道为什么会这样,或者我做错了什么?
我在下面提供的代码是我放在一起的一个基本示例,它演示了此问题以及我试图实现的桨运动(这几乎反映了我的Pong项目)。右侧拨片正确移动,而左侧拨片则不正确。预先感谢您的帮助!
from Tkinter import *
import random
WIDTH = 500
HEIGHT = 500
PAD_WIDTH = 10
PAD_HEIGHT = 80
HALF_PAD_WIDTH = PAD_WIDTH / 2
HALF_PAD_HEIGHT = PAD_HEIGHT / 2
class Example(Frame, object):
def __init__(self, master):
super(Example, self).__init__(master)
self._paddle1_pos = 200
self._paddle2_pos = 200
self._paddle1_vel = 0
self._paddle2_vel = 0
self.initUI()
def initUI(self):
scn_cent_height = self.master.winfo_screenheight() // 2 - HEIGHT // 2
scn_cent_width = self.master.winfo_screenwidth() // 2 - WIDTH // 2
self.master.geometry("%sx%s+%s+%s" % (WIDTH, HEIGHT, scn_cent_width, scn_cent_height))
self.master.minsize(WIDTH, HEIGHT)
self.master.title("Example Pong Paddles")
self._canvasFrame = Frame(self.master)
self._canvasFrame.pack(expand=True, fill=BOTH)
self._canvas = Canvas(self._canvasFrame, bg="black", highlightthickness=0, bd=0)
self._canvas.pack(fill=BOTH, expand=True)
self.update_idletasks()
# Key handlers
self.master.bind("<KeyPress>", self.keydown)
self.master.bind("<KeyRelease>", self.keyup)
while True:
self._canvas.after(1)
self._canvas.delete("all")
self.draw()
self._canvas.update()
def draw(self):
self._cheight = self._canvasFrame.winfo_height()
self._cwidth = self._canvasFrame.winfo_width()
# Draw mid line and gutters
self._rline = self._canvas.create_line(self._cwidth / 2, 0, self._cwidth / 2, self._cheight, width=1, fill="White")
self._mline = self._canvas.create_line(PAD_WIDTH, 0, PAD_WIDTH, self._cheight, width=1, fill="White")
self._lline = self._canvas.create_line(self._cwidth - PAD_WIDTH, 0, self._cwidth - PAD_WIDTH, self._cheight, width=1, fill="White")
# Update paddle's vertical position, keep paddle on the screen
# Paddle 1 - Check height and update position
if self._paddle1_pos + self._paddle1_vel >= HALF_PAD_HEIGHT and self._paddle1_pos + self._paddle1_vel <= HEIGHT - HALF_PAD_HEIGHT:
self._paddle1_pos += self._paddle1_vel
# Paddle 2 - Check height and update position
if self._paddle2_pos + self._paddle2_vel >= HALF_PAD_HEIGHT and self._paddle2_pos + self._paddle2_vel <= HEIGHT - HALF_PAD_HEIGHT:
self._paddle2_pos += self._paddle2_vel
# Draw paddles
self._p1paddle = self._canvas.create_line([HALF_PAD_WIDTH, self._paddle1_pos - HALF_PAD_HEIGHT],
[HALF_PAD_WIDTH, self._paddle1_pos + HALF_PAD_HEIGHT], width=PAD_WIDTH, fill="White")
self._p2paddle = self._canvas.create_line([self._cwidth - HALF_PAD_WIDTH, self._paddle2_pos - HALF_PAD_HEIGHT],
[self._cwidth - HALF_PAD_WIDTH, self._paddle2_pos + HALF_PAD_HEIGHT], width=PAD_WIDTH, fill="White")
# Draw paddles
self._p1paddle = self._canvas.create_line([HALF_PAD_WIDTH, self._paddle1_pos - HALF_PAD_HEIGHT],
[HALF_PAD_WIDTH, self._paddle1_pos + HALF_PAD_HEIGHT], width=PAD_WIDTH, fill="White")
self._p2paddle = self._canvas.create_line([self._cwidth - HALF_PAD_WIDTH, self._paddle2_pos - HALF_PAD_HEIGHT],
[self._cwidth - HALF_PAD_WIDTH, self._paddle2_pos + HALF_PAD_HEIGHT], width=PAD_WIDTH, fill="White")
def keydown(self, key):
key = key.keysym
if key == "w":
self._paddle1_vel = -10
elif key == "s":
self._paddle1_vel = 10
elif key == "Up":
self._paddle2_vel = -10
elif key == "Down":
self._paddle2_vel = 10
def keyup(self, key):
key = key.keysym
if key == "w":
self._paddle1_vel = 0
elif key == "s":
self._paddle1_vel = 0
elif key == "Up":
self._paddle2_vel = 0
elif key == "Down":
self._paddle2_vel = 0
def main():
root = Tk()
example = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
答案 0 :(得分:0)
为了给遇到此问题的任何其他人带来好处,我只是想补充一下,我能够将其源追溯到我的Anaconda虚拟环境(对于Python 2和Python 3,每个人都有一个)。在测试中,我能够在专门使用这些环境时重现此问题,但是在Anaconda之外使用Python 2(mac框架构建)或Python 3(通过Brew安装)时无法重现此问题。我清除了两个Anaconda虚拟环境以防万一,那里的东西弄乱了,然后重新构建了它们(即Python 2和3的全新安装),并且仍然能够重现此问题(无需安装任何其他模块)。我只能推测,Anaconda安装的python与系统框架的一部分或单独安装的python之间存在某些差异。
还要注意,事实证明,当我在@Novel的上述注释中在Python 3上成功测试时,我无意中在系统Python 3上进行了测试,而不是在Anaconda Python 3虚拟环境中进行了测试。
编辑: 事实证明,这个问题实际上是由于我的python安装所使用的Tkinter版本(Tcl / Tk)。我的笔记本电脑上的python框架使用Tk 8.5.9,而Anaconda安装使用的是8.6.8。在测试中,当我在Tk 8.6.8的python 2.7.16和3.7.3中运行Pong脚本时遇到了这个问题,但在与Tk 8.5.9相同的python版本上运行得很好。我不确定这是Tk的问题,还是Tk 8.6.8与MacOS框架之间的某些不兼容(因为该框架本身使用8.5.9)。
答案 1 :(得分:-1)
您的代码非常混乱,需要进行重构,因此我做到了。一些注意事项:
update()
或update_idletasks()
方法是不得已的方法;普通代码没有它们。通过after()
使用tkinter的主循环。这将使您的窗口更具反应性。 _
无济于事,并且使其难以阅读和输入;别说了。 -
try:
import tkinter as tk # python3 detected
except ImportError:
import Tkinter as tk # python2 detected
WIDTH = 500
HEIGHT = 500
PAD_WIDTH = 10
PAD_HEIGHT = 80
VELOCITY = 10
HALF_PAD_WIDTH = PAD_WIDTH // 2
HALF_PAD_HEIGHT = PAD_HEIGHT // 2
P1_UP = 111 # Up arrow key
P1_DOWN = 116 # Down arrrow key
P2_UP = 25 # 'w' key
P2_DOWN = 39 # 's' key
class Example(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.keys = {}
self.initUI()
# Key handlers
self.master.bind("<KeyPress>", self.keydown)
self.master.bind("<KeyRelease>", self.keyup)
self.draw() # add the game loop to the mainloop
def initUI(self):
scn_cent_height = self.master.winfo_screenheight() // 2 - HEIGHT // 2
scn_cent_width = self.master.winfo_screenwidth() // 2 - WIDTH // 2
self.master.geometry("%sx%s+%s+%s" % (WIDTH, HEIGHT, scn_cent_width, scn_cent_height))
self.master.minsize(WIDTH, HEIGHT)
self.master.title("Example Pong Paddles")
self.canvas = tk.Canvas(self, bg="black", highlightthickness=0, bd=0, width=WIDTH, height=HEIGHT)
self.canvas.pack(fill=tk.BOTH, expand=True)
# Draw mid line and gutters
self.rline = self.canvas.create_line(WIDTH//2, 0, WIDTH//2, HEIGHT, width=1, fill="White")
self.mline = self.canvas.create_line(PAD_WIDTH, 0, PAD_WIDTH, HEIGHT, width=1, fill="White")
self.lline = self.canvas.create_line(WIDTH - PAD_WIDTH, 0, WIDTH - PAD_WIDTH, HEIGHT, width=1, fill="White")
# Draw paddles
self.p1paddle = self.canvas.create_line([HALF_PAD_WIDTH, HEIGHT//2 - HALF_PAD_HEIGHT],
[HALF_PAD_WIDTH, HEIGHT//2 + HALF_PAD_HEIGHT], width=PAD_WIDTH, fill="White")
self.p2paddle = self.canvas.create_line([WIDTH - HALF_PAD_WIDTH, HEIGHT//2 - HALF_PAD_HEIGHT],
[WIDTH - HALF_PAD_WIDTH, HEIGHT//2 + HALF_PAD_HEIGHT], width=PAD_WIDTH, fill="White")
def draw(self):
if self.keys.get(P2_UP) and self.canvas.coords(self.p1paddle)[1] > 0:
self.canvas.move(self.p1paddle, 0, -VELOCITY)
if self.keys.get(P2_DOWN) and self.canvas.coords(self.p1paddle)[3] < HEIGHT:
self.canvas.move(self.p1paddle, 0, VELOCITY)
if self.keys.get(P1_UP) and self.canvas.coords(self.p2paddle)[1] > 0:
self.canvas.move(self.p2paddle, 0, -VELOCITY)
if self.keys.get(P1_DOWN) and self.canvas.coords(self.p2paddle)[3] < HEIGHT:
self.canvas.move(self.p2paddle, 0, VELOCITY)
self.after(10, self.draw)
def keydown(self, key):
self.keys[key.keycode] = True
def keyup(self, key):
self.keys[key.keycode] = False
def main():
root = tk.Tk()
example = Example(root)
example.pack()
root.mainloop()
if __name__ == '__main__':
main()
也许,偶然地,那里的一些改进也将解决您原来的问题。