Python Turtle/Tkinter计时器正在加速



我认为用Python Turtle Graphics制作动画的标准方法是做一些类似的事情

def animate():
# move stuff
ontimer(animate, delay)

查看turtle的源代码,可以在后台实现tkinterafter()

有人能解释一下为什么在下面的程序中,动画在运行时会急剧加速和减速吗?

我的理论是,由于每次调用ontimer()时都会创建一个新的.after()id,因此存在多个相互干扰的计时器?或者这只是程序中随机性的结果?或者回调之间的短间隔可能会导致问题?

from random import *
from turtle import *
import math
class Vector(object):
def __init__(self, x = 0.0, y = 0.0):
self.x = x
self.y = y
def move(self, other):
""" Move vector by other (in-place)."""
self.__iadd__(other)
def __iadd__(self, other):
if isinstance(other, Vector):
self.x += other.x
self.y += other.y
else:
self.x += other
self.y += other
def rotate(self, angle):
"""Rotate vector counter-clockwise by angle (in-place)."""
radians = angle * math.pi / 180.0
cosine = math.cos(radians)
sine = math.sin(radians)
x = self.x
y = self.y
self.x = x * cosine - y * sine
self.y = y * cosine + x * sine
ant = Vector(0, 0)
aim = Vector(2, 0)
def wrap(value):
"Wrap value around -200 and 200."
if value > 200:
value = -200
elif value < -200:
value = 200
return value
def draw():
"Move ant and draw screen."
ant.move(aim)
ant.x = wrap(ant.x)
ant.y = wrap(ant.y)
aim.move(random() - 0.5)
aim.rotate(random() * 10 - 5)
clear()
goto(ant.x, ant.y)
dot(10)
if running:
ontimer(draw, 50)
setup(420, 420, 370, 0)
hideturtle()
tracer(False)
up()
running = True
draw()
done()

我认为您的动画会加速和减速,因为您使用了tracer(),但未能执行显式update()tracer()函数会关闭动画,但一些乌龟操作会产生隐含的update()作为副作用。由于您没有执行明确的update(),因此只能获得由这些副作用引起的随机更新。

下面我添加了一个明确的update(),并简化了代码,使乌龟本身成为移动对象,而不是冲压清除。(顺便说一句,如果你保存stamp()的结果,你可以要求它自行清除。(

我还从圆圈切换到了乌龟光标图像,并添加了逻辑以将标题设置为运动方向:

from random import random
from turtle import Screen, Turtle, Vec2D
from math import pi, cos, sin
class Vector(object):
def __init__(self, x=0.0, y=0.0):
self.x = x
self.y = y
def move(self, other):
""" Move vector by other (in-place)."""
self.__iadd__(other)
self.wrap()
def __iadd__(self, other):
if isinstance(other, Vector):
self.x += other.x
self.y += other.y
else:
self.x += other
self.y += other
def rotate(self, degrees):
""" Rotate vector counter-clockwise by angle (in-place). """
radians = degrees * pi / 180.0
cosine = cos(radians)
sine = sin(radians)
x = self.x
y = self.y
self.x = x * cosine - y * sine
self.y = y * cosine + x * sine
def position(self):
return Vec2D(self.x, self.y)
def wrap(self):
""" Wrap value around -200 and 200. """
x = self.x
y = self.y
if x > 200:
self.x = -200
elif x < -200:
self.x = 200
if y > 200:
self.y = -200
elif y < -200:
self.y = 200
def draw():
""" Move ant and draw screen. """
ant.move(aim)
position = ant.position()
turtle.setheading(turtle.towards(position))
turtle.setposition(position)
screen.update()
aim.move(random() - 0.5)
aim.rotate(random() * 10 - 5)
screen.ontimer(draw, 75)
screen = Screen()
screen.setup(420, 420)
screen.tracer(False)
turtle = Turtle()
turtle.hideturtle()
turtle.shape('turtle')
turtle.shapesize(0.5)
turtle.penup()
turtle.showturtle()
ant = Vector(0, 0)
aim = Vector(2, 0)
draw()
screen.mainloop()

最新更新