【问题标题】:Python Turtle/Tkinter Timers AcceleratingPython Turtle/Tkinter 计时器加速
【发布时间】:2020-03-26 08:45:37
【问题描述】:

我认为使用 Python Turtle Graphics 制作动画的典型方法是像

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

查看turtle 的源代码,它在后台实现tkinter after()

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

我的理论是,由于每次调用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()

【问题讨论】:

  • 应该是随机性造成的。
  • 您运行过它并查看过它的行为吗?它看起来不仅仅是随机运动引起的变化。
  • 是的,我有。只有draw()done()之前的除外)通过ontimer调用自己,所以不应该是多个ontimer任务的原因。
  • 如果您查看来自Screen.getcanvas().after(...) 的ID,每次函数调用自身时都会创建一个新计时器。每一个都没有明确的破坏。通过在重复函数开始时显式销毁当前的.after() id,我设法修复了另一个程序中的错误。不过,关于这个程序,它的加速速度没有超出您对随机值的预期吗?

标签: python tkinter timer turtle-graphics


【解决方案1】:

我认为你的动画加速和减速是因为你使用了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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-12
    • 2019-04-11
    • 2017-10-11
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 2020-05-17
    • 2016-12-09
    相关资源
    最近更新 更多