我正在使用画布在Tkinter创建一个Shoot'Em Up游戏。用户控制一个精灵,该精灵在沿着x轴面向的方向上不断射击子弹。
我试图让子弹在屏幕上移动时遇到问题。我正在使用while True
循环来保持子弹持续移动,但这会导致程序冻结。
根据我的研究,我了解到我可能不得不使用线程来阻止maintop冻结,但是我无法在Tkinter网上找到任何易于遵循的线程指南。
这是我的代码:
from Tkinter import *
from Tkinter import Canvas
import time
window1 = Tk()
window1.title("Shoot 'Em Up")
window1.config(background="black")
window1.geometry("600x300")
def move_spryte1_up(event):
xspeed = 0
yspeed = -10
canvas.move(spryte1, xspeed, yspeed)
Tk.update(window1)
def move_spryte1_down(event):
xspeed = 0
yspeed = 10
canvas.move(spryte1, xspeed, yspeed)
Tk.update(window1)
def move_spryte1_left(event):
xspeed = -10
yspeed = 0
canvas.move(spryte1, xspeed, yspeed)
Tk.update(window1)
def move_spryte1_right(event):
xspeed = 10
yspeed = 0
canvas.move(spryte1, xspeed, yspeed)
Tk.update(window1)
def bullets():
spryte1_pos = canvas.bbox(spryte1)
newpos1 = spryte1_pos[1]
newpos2 = spryte1_pos[2]-30
newpos3 = spryte1_pos[3]-20
spryte2 = canvas.create_rectangle(newpos1, newpos2, newpos3, newpos3, fill="blue")
print(spryte1_pos)
print(newpos1)
print(newpos2)
print(newpos3)
while True:
canvas.move(spryte2, 10, 0)
Tk.update(window1)
time.sleep(0.1)
canvas = Canvas(window1, width=600, height=300, bg="black", bd=0, highlightthickness=1, relief="ridge", highlightbackground="black")
canvas.pack()
points = [20, 40, 35, 40, 35, 30, 50, 40, 65, 40, 80, 52.5, 65, 65, 50, 65, 35, 75, 35, 65, 20, 65, 30, 62, 20, 59, 30, 56, 20, 53, 30, 50, 20, 47, 30, 44]
spryte1 = canvas.create_polygon(points, outline='red', fill='gray')
bullets()
canvas.tag_raise(spryte1)
window1.bind('<Up>', move_spryte1_up)
window1.bind('<Down>', move_spryte1_down)
window1.bind('<Left>', move_spryte1_left)
window1.bind('<Right>', move_spryte1_right)
window1.mainloop()
任何帮助将不胜感激!
编辑:这个问题与python - While Loop causes entire program to crash in Tkinter 略有不同,因为这是我最初在tkinter中寻找线程帮助时出现的问题。但是,我试图提出解决方案,但发现它没有解决我的问题
答案 0 :(得分:0)
您不需要线程,并且您不需要使用while循环来实现这一点。
你已经有一个无限循环运行 - 事件循环(例如:mainloop
)。您可以使用after
方法将工作放在将来要执行的事件队列中。要执行动画,只需调用一个函数来绘制一个帧,然后让该函数将自身添加回事件队列以绘制下一帧。
以下是对代码的简单修改,以说明要点:
def bullets():
spryte1_pos = canvas.bbox(spryte1)
newpos1 = spryte1_pos[1]
newpos2 = spryte1_pos[2]-30
newpos3 = spryte1_pos[3]-20
spryte2 = canvas.create_rectangle(newpos1, newpos2, newpos3, newpos3, fill="blue")
shoot(spryte2, 10, 0)
def shoot(spryte, x, y):
canvas.move(spryte, x, y)
x0,y0,x1,y1 = canvas.bbox(spryte)
if x0 < 600
# call again in 100ms, unless the bullet is off the screen
canvas.after(100, shoot, spryte, x, y)
在它陷入困境之前,画布可能会像这样移动几十个sprytes。
顺便说一下,您还可以删除移动函数中对Tk.update(window1)
的所有调用 - 它会增加开销并降低程序速度。作为一般经验法则,您几乎永远不会致电update
。