Threading в Tkinter, чтобы остановить Mainloop от замерзания - PullRequest
0 голосов
/ 30 мая 2018

Я создаю игру Shoot 'Em Up в Tkinter, используя холст.Пользователь управляет спрайтом, который непрерывно стреляет пулями в направлении, обращенном вдоль оси x.

Я столкнулся с проблемой при попытке анимировать пулю, движущуюся по экрану.Я использую петлю while True, чтобы поддерживать непрерывное движение пули, однако это приводит к зависанию программы.

Из моих исследований я понимаю, что мне, возможно, придется использовать многопоточность, чтобы остановить зависание главной панели,однако я не смог найти никаких простых руководств по многопоточности в 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()

Любая помощь будет признательна!

Edit: этот вопрос немного отличается от python - в то время как Loop вызывает сбой всей программы в Tkinter , так как это был вопрос, который возник, когда я первоначально искал помощь с многопоточностью в tkinter.Тем не менее, я попытался представить решение, но обнаружил, что оно не решает мою проблему

1 Ответ

0 голосов
/ 30 мая 2018

Вам не нужны потоки, и вам не нужен цикл 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)

Возможно, холст может обрабатывать несколько десятков спрайтов, перемещаемых таким образом, до того, как он сваливается.

Кстати, вы также можете удалить все вызовы Tk.update(window1) в ваших функциях перемещения - это увеличивает накладные расходы и замедляет работу программы.Как правило, вы должны почти никогда звонить update.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...