Get smooth motion by multi-threading Python turtle graphics

北城以北 提交于 2019-12-13 05:16:15

问题


This is my first question!

I finished making a simple space invaders game in Python turtle graphics and noticed an annoying problem: the more objects I have on my screen, the slower the program runs.

My friend told me that I need to use multi-threading so that all the commands will run concurrently, and that way, the game will run smooth.

I added only the relevent code for my problem which is to move two enemy invaders from side to side of the screen. I think this will be enough to help me through this.

With this code, the enemies get stuck in their own place a couple of miliseconds every now and then. It's very noticable, what should I do?

one_enemy = turtle.Turtle()
one_enemy.shape("Invader.gif")
one_enemy.penup()
one_enemy.speed(0)
x = random.randint(-200, 200)
y = random.randint(100, 200)
one_enemy.setposition(x, y)

two_enemy = turtle.Turtle()
two_enemy.shape("Invader.gif")
two_enemy.penup()
two_enemy.speed(0)
x = random.randint(-200, 200)
y = random.randint(100, 200)
two_enemy.setposition(x, y)

def move_enemy_horizontally(enemy, direction):
    while True:
        while direction == "right":
            x = enemy.xcor()
            x += enemyspeed
            enemy.setx(x)
            if enemy.xcor() > 288:
                y = enemy.ycor()
                y -= 50
                enemy.sety(y)
                direction = "left"
        while direction == "left":
            x = enemy.xcor()
            x -= enemyspeed
            enemy.setx(x)
            if enemy.xcor() < -288:
                y = enemy.ycor()
                y -= 50
                enemy.sety(y)
                direction = "right"

t = threading.Thread(target=move_enemy_horizontally, args=(one_enemy, direction))
t.start()
t2 = threading.Thread(target=move_enemy_horizontally, args=(two_enemy, direction))
t2.start()

回答1:


I'm surprised your code works at all -- when I finish it off and run it, only one turtle moves. Perhaps it's a difference between Windows and Unix or some such. Regardless, my belief has been that you can't do tkinter/turtle graphics in any thread but the main one. So, I've developed this approach which allows the secondary threads to calculate things about their turtle but ultimately pass the graphics command onto the primary thread:

from turtle import Screen, Turtle
from random import randint
from threading import Thread, active_count
from queue import Queue

QUEUE_SIZE = 1
ENEMY_SPEED = 3

def move_enemy_horizontally(enemy, direction):
    x, y = enemy.position()

    while True:
        while direction == "right":

            if x > 288:
                y -= 50
                actions.put((enemy.sety, y))
                direction = "left"
            else:
                x += ENEMY_SPEED
                actions.put((enemy.setx, x))

        while direction == "left":
            if x < -288:
                y -= 50
                actions.put((enemy.sety, y))
                direction = "right"
            else:
                x -= ENEMY_SPEED
                actions.put((enemy.setx, x))

def process_queue():
    while not actions.empty():
        action, argument = actions.get()
        action(argument)

    if active_count() > 1:
        screen.ontimer(process_queue, 100)

actions = Queue(QUEUE_SIZE)

x, y = randint(-200, 200), randint(100, 200)

direction = "right"

for dy in range(2):
    for dx in range(2):
        enemy = Turtle("turtle", visible=False)
        enemy.speed('fastest')
        enemy.setheading(270)
        enemy.penup()
        enemy.setposition(x + dx * 60, y + dy * 100)
        enemy.showturtle()

        Thread(target=move_enemy_horizontally, args=(enemy, direction), daemon=True).start()

    direction = ["left", "right"][direction == "left"]

screen = Screen()

process_queue()

screen.mainloop()

I'm not saying that threads are the answer to your problem, nor that they won't slow down as you add more enemies. Another approach might be to treat the enemies more as a block, not complete individuals, and use timer events within the graphics library instead of threads.



来源:https://stackoverflow.com/questions/53090453/get-smooth-motion-by-multi-threading-python-turtle-graphics

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!