问题
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