为什么新的 Turtle 形状有奇怪的方向(不是我定义的那个)?

Why new Turtle shapes have odd orientation (not the one I defined)?

我想用 Python 和 Turtle 创建 Pong 的另一个克隆。我的目标是让我的学生(在 Python 开始编码)进一步练习。

我想创建一个形状为水平填充矩形的 Turtle,就像一个程式化的桨。但是当我创建一个我认为方便的形状时,我得到了一个旋转的(垂直的)桨而不是我希望的水平的桨。

这是演示这种奇怪行为的代码。

from turtle import *

begin_poly()
fd(200)
left(90)
fd(40)
left(90)
fd(200)
left(90)
fd(40)
left(90)
end_poly()
shape = get_poly()
register_shape("drawn", shape)

polyNotOk = ( (0,0), (100, 0), (100, 20), (0, 20) ) 
register_shape("polyNotOk", polyNotOk)

polyOk = ( (0,0), (0, 100), (20, 100), (20, 0) ) 
register_shape("polyOk", polyOk)

t1 = Turtle(shape="drawn")
t2 = Turtle(shape="polyNotOk")
t3 = Turtle(shape="polyOk")

t1.color("black")
t2.color("red")
t3.color("blue")

t1.stamp()
t2.stamp()
t3.stamp()

t1.goto(100,200)
t2.goto(100,-50)
t3.goto(100,-150)

t1.forward(100)
t2.forward(100)
t3.forward(100)

mainloop()

因此,正如您所看到的,如果您 运行 代码,第一个绘图就可以了,具有水平形状。但是当我戳龟的时候t1,形状是垂直的

通过 polyNotOk 定义的第二个形状存在相同问题(具有允许获得水平桨的 x 和 y 坐标值)。我需要创建一个 "vertical" 多边形以获得水平桨。

所以我能够找到解决方法。但是我仍然对这个解决方案不满意,所以我要求出色的解释;-)提前致谢。

我希望阐明这种奇怪的行为,而不是为它辩护。关于绘制的光标,首先要记住的是 (0, 0) 落在光标绘图中的位置,即光标围绕其旋转的中心点和光标中落在任何点上的像素 goto()

可以在 shapesize() 方法文档中找到一些见解:

shapesize(stretch_wid=None, stretch_len=None, outline=None)

stretch_wid is stretchfactor perpendicular to orientation
stretch_len is stretchfactor in direction of turtles orientation.

也就是说,如果光标处于默认(东)方向,这将颠倒 X 和 Y 的方向。我相信这就是您在绘图中看到的。 X 平面垂直于方向(垂直),Y 平面在方向(水平)上。与我们通常期望的相反。

这似乎不是 Shape() class 的错误,而是隐藏在游标逻辑中。它可能是历史文物——如果我们更改为 mode("logo") 和 运行 您的代码,我们将得到:

考虑到 "logo" 模式的默认方向是北,并且比以前更一致,我们可能会期待更多。

无论如何,我会以不同的方式制作我的球拍。我不使用自定义光标,而是使用 turtle 的 square 光标,并根据需要使用 shapesize():

对其进行整形
from turtle import Screen, Turtle

CURSOR_SIZE = 20

screen = Screen()

t0 = Turtle("square")
t0.shapesize(20 / CURSOR_SIZE, 100 / CURSOR_SIZE)

t0.color("green")

screen.exitonclick()

逻辑(不是图形)仍然与您的预期不同,但至少文档告诉了我们这一点。但是,我 真正 倾向于做的是将球拍方向错误,并使用 settiltangle(),但不像你那样作为解决方法,而是让我的球拍面向一个方向移动,但向另一个方向移动:

from turtle import Screen, Turtle

CURSOR_SIZE = 20

screen = Screen()

t0 = Turtle("triangle")
t0.shapesize(100 / CURSOR_SIZE, 20 / CURSOR_SIZE)
t0.settiltangle(90)
t0.penup()

t0.color("green")
t0.speed("slowest")  # for demonstration purposes

t0.forward(300)
t0.backward(600)
t0.forward(300)

screen.exitonclick()

请注意,我可以使用 forward(10)backward(10) 来移动我的球拍,而不必做 t0.setx(t0.xcor() + 10) 这样糟糕的事情。非常适合 Space 玩家面朝上但向侧面移动的入侵者类型游戏。