如何使对象顺利移动tkinter

时间:2018-05-20 02:24:34

标签: python tkinter

按下按钮移动"坦克"时,它会启动,但随后会停止并重新开始。有没有办法让它不这样做?

from tkinter import *
from tkinter.constants import LEFT
root = Tk()
c = Canvas(root, width=400, height=400)
tank = c.create_rectangle(200,200,250, 250, outline = 'dark green', 
fill='dark green')
c.pack()

class Tank:
    def move_left(self):
        c.move(tank, -5, 0)
    def move_right(self):
        c.move(tank, 5,0)
    def move_up(self):
        c.move(tank, 0, -5) 
    def move_down(self):
        c.move(tank, 0, 5)           

c.bind('<Left>', Tank.move_left)
c.bind('<Right>', Tank.move_right)
c.bind('<Up>', Tank.move_up)
c.bind('<Down>', Tank.move_down)
c.focus_set()            
root.mainloop()     

2 个答案:

答案 0 :(得分:1)

您可以使用几个布尔值(向上,向右,向左,向下)来表示坦克是否朝向一个方向。按下某个键时,将布尔值设置为true,当它被释放时,设置布尔值为false。使用单独的线程/ while循环使用import threading进行游戏循环,并在游戏循环中检查其中一个布尔值是否为真。例如,如果表示right的布尔值为true,则程序将添加到tank的x坐标。

答案 1 :(得分:0)

问题的第一部分是捕获KeyPress and KeyRelease events而不是关键事件。

但事情变得复杂了。你希望坦克每移动120毫秒,尽可能不快,对吧?所以,你唯一能做的就是设置after回调,这样你就可以每120毫秒运行一些代码,并让关键事件设置一些标志,告诉你如何移动坦克(或不移动它)基于什么被按下。

这是可行的,但下一个问题甚至更大:Tkinter在重新映射您的操作系统之后捕获高级别的关键事件(因此您得到E而不是shift和{{1 }}),包括自动重复。要解决这个问题,您必须编写一些代码来手动执行"debouncing"

仍然可行,但这并不容易。并且不完美 - 快速按下按键可以欺骗你提出的任何去抖动算法,快速按下按键是你经常想要在游戏中允许的。

更好的解决方案可能是从一个完全不同的库开始,比如PyGame Zero,而不是Tkinter。为游戏设计的库将有一个框架循环,因此您不需要使用e并检查一堆标志,将捕获&#34; raw&#34;键盘事件,所以你可以立即响应它们等等。当你进一步,并希望,例如,使用精灵为你的坦克,你不必重新发明这些轮子,就像你对Tkinter的方式。