使用 Python 龟图形和图章的流畅动画
Smooth Animation with Python Turtle Graphics and Stamps
是否有可能使用 Turtle Graphics 和 stamp()
方法获得比下面代码给出的更流畅的动画效果?
我曾尝试过在move_blocks
中使用stamper.clearstamps(1)
只清除第一个图章,并且每次只画新的方块,但结果看起来是一样的。我认为问题可能是在后台调用 Screen.update()
,尽管我还没有确认这一点。
import turtle
def move_blocks():
stamper.clearstamps()
new_block = blocks[-1].copy()
new_block[0] += 20
if new_block[0] > 250:
new_block[0] = - 250
blocks.append(new_block)
blocks.pop(0)
for block in blocks:
stamper.goto(block[0], block[1])
stamper.stamp()
screen.update()
turtle.ontimer(move_blocks, 100)
screen = turtle.Screen()
screen.setup(500, 500)
screen.tracer(0) # Turn off automatic animation
stamper = turtle.Turtle("square")
stamper.penup()
blocks = [[0, 0], [20, 0], [40, 0], [60, 0]]
for block in blocks:
stamper.goto(block[0], block[1])
stamper.stamp()
move_blocks()
turtle.done()
非常感谢任何帮助。
I think the problem might be that stamping calls Screen.update() in
the background, although I haven't confirmed this.
这似乎是真的,而且很容易证实,但不一定是全部问题。下面是我对你的代码进行的修改,通过只删除失效的邮票 ID 来优化它,但它看起来并不比你的好。你可以看到我已经注释掉了 screen.update()
这没有什么区别:
from turtle import Screen, Turtle
def move_blocks():
new_block = blocks.pop(0)
new_block[0] = blocks[-1][0] + 20
if new_block[0] > 250:
new_block[0] = -250
blocks.append(new_block)
stamper.goto(new_block)
stamper.clearstamp(ids.pop(0))
ids.append(stamper.stamp())
# screen.update()
screen.ontimer(move_blocks, 100)
screen = Screen()
screen.setup(500, 500)
screen.tracer(0) # Turn off automatic animation
stamper = Turtle('square')
stamper.hideturtle()
stamper.penup()
blocks = [[0, 0], [20, 0], [40, 0], [60, 0]]
ids = []
for block in blocks:
stamper.goto(block)
ids.append(stamper.stamp())
# screen.update()
move_blocks()
screen.exitonclick()
自作聪明,我想比较一下绘图和冲压,但结果是一样的,填充操作触发 screen.update()
并让我们回到起点:
from turtle import Screen, Turtle
CURSOR_SIZE = 20
def move_blocks():
filler.clear()
new_block = blocks.pop(0)
new_block[0] = blocks[-1][0] + 20
if new_block[0] > 250:
new_block[0] = -250
blocks.append(new_block)
for block in blocks:
fill(block)
# screen.update()
screen.ontimer(move_blocks, 100)
def fill(position):
filler.goto(position)
filler.begin_fill()
for _ in range(4):
filler.forward(CURSOR_SIZE)
filler.left(90)
filler.end_fill()
screen = Screen()
screen.setup(500, 500)
screen.tracer(0) # Turn off automatic animation
filler = Turtle()
filler.hideturtle()
filler.penup()
blocks = [[0, 0], [20, 0], [40, 0], [60, 0]]
for block in blocks:
fill(block)
# screen.update()
move_blocks()
screen.exitonclick()
最后,我做了一个在 tracer()
控制下的实现,程序员发起了 screen.update()
调用。我只是重塑光标并移动它以进行比较。这次把screen.update()
注释掉就可以看出区别了
from turtle import Screen, Turtle
CURSOR_SIZE = 20
CURSOR_LENGTH = 80
STEP_SIZE = 1
def move():
x = turtle.xcor() + STEP_SIZE
if x - CURSOR_LENGTH/2 > 250:
turtle.setx(-250 - CURSOR_LENGTH/2)
else:
turtle.forward(STEP_SIZE)
screen.update()
screen.ontimer(move, 5 * STEP_SIZE)
screen = Screen()
screen.setup(500, 500)
screen.tracer(0) # Turn off automatic animation
turtle = Turtle()
turtle.shape('square')
turtle.shapesize(stretch_len=CURSOR_LENGTH/CURSOR_SIZE)
turtle.penup()
screen.update()
move()
screen.exitonclick()
但是,此实现指出,较早的视觉性能不佳也是由于步长过大造成的——如果您更改 STEPSIZE = CURSOR_SIZE
,那么您将拥有相同的步长和相同的性能,如你的原创。
是否有可能使用 Turtle Graphics 和 stamp()
方法获得比下面代码给出的更流畅的动画效果?
我曾尝试过在move_blocks
中使用stamper.clearstamps(1)
只清除第一个图章,并且每次只画新的方块,但结果看起来是一样的。我认为问题可能是在后台调用 Screen.update()
,尽管我还没有确认这一点。
import turtle
def move_blocks():
stamper.clearstamps()
new_block = blocks[-1].copy()
new_block[0] += 20
if new_block[0] > 250:
new_block[0] = - 250
blocks.append(new_block)
blocks.pop(0)
for block in blocks:
stamper.goto(block[0], block[1])
stamper.stamp()
screen.update()
turtle.ontimer(move_blocks, 100)
screen = turtle.Screen()
screen.setup(500, 500)
screen.tracer(0) # Turn off automatic animation
stamper = turtle.Turtle("square")
stamper.penup()
blocks = [[0, 0], [20, 0], [40, 0], [60, 0]]
for block in blocks:
stamper.goto(block[0], block[1])
stamper.stamp()
move_blocks()
turtle.done()
非常感谢任何帮助。
I think the problem might be that stamping calls Screen.update() in the background, although I haven't confirmed this.
这似乎是真的,而且很容易证实,但不一定是全部问题。下面是我对你的代码进行的修改,通过只删除失效的邮票 ID 来优化它,但它看起来并不比你的好。你可以看到我已经注释掉了 screen.update()
这没有什么区别:
from turtle import Screen, Turtle
def move_blocks():
new_block = blocks.pop(0)
new_block[0] = blocks[-1][0] + 20
if new_block[0] > 250:
new_block[0] = -250
blocks.append(new_block)
stamper.goto(new_block)
stamper.clearstamp(ids.pop(0))
ids.append(stamper.stamp())
# screen.update()
screen.ontimer(move_blocks, 100)
screen = Screen()
screen.setup(500, 500)
screen.tracer(0) # Turn off automatic animation
stamper = Turtle('square')
stamper.hideturtle()
stamper.penup()
blocks = [[0, 0], [20, 0], [40, 0], [60, 0]]
ids = []
for block in blocks:
stamper.goto(block)
ids.append(stamper.stamp())
# screen.update()
move_blocks()
screen.exitonclick()
自作聪明,我想比较一下绘图和冲压,但结果是一样的,填充操作触发 screen.update()
并让我们回到起点:
from turtle import Screen, Turtle
CURSOR_SIZE = 20
def move_blocks():
filler.clear()
new_block = blocks.pop(0)
new_block[0] = blocks[-1][0] + 20
if new_block[0] > 250:
new_block[0] = -250
blocks.append(new_block)
for block in blocks:
fill(block)
# screen.update()
screen.ontimer(move_blocks, 100)
def fill(position):
filler.goto(position)
filler.begin_fill()
for _ in range(4):
filler.forward(CURSOR_SIZE)
filler.left(90)
filler.end_fill()
screen = Screen()
screen.setup(500, 500)
screen.tracer(0) # Turn off automatic animation
filler = Turtle()
filler.hideturtle()
filler.penup()
blocks = [[0, 0], [20, 0], [40, 0], [60, 0]]
for block in blocks:
fill(block)
# screen.update()
move_blocks()
screen.exitonclick()
最后,我做了一个在 tracer()
控制下的实现,程序员发起了 screen.update()
调用。我只是重塑光标并移动它以进行比较。这次把screen.update()
注释掉就可以看出区别了
from turtle import Screen, Turtle
CURSOR_SIZE = 20
CURSOR_LENGTH = 80
STEP_SIZE = 1
def move():
x = turtle.xcor() + STEP_SIZE
if x - CURSOR_LENGTH/2 > 250:
turtle.setx(-250 - CURSOR_LENGTH/2)
else:
turtle.forward(STEP_SIZE)
screen.update()
screen.ontimer(move, 5 * STEP_SIZE)
screen = Screen()
screen.setup(500, 500)
screen.tracer(0) # Turn off automatic animation
turtle = Turtle()
turtle.shape('square')
turtle.shapesize(stretch_len=CURSOR_LENGTH/CURSOR_SIZE)
turtle.penup()
screen.update()
move()
screen.exitonclick()
但是,此实现指出,较早的视觉性能不佳也是由于步长过大造成的——如果您更改 STEPSIZE = CURSOR_SIZE
,那么您将拥有相同的步长和相同的性能,如你的原创。