Python Turtle 从坐标创建自定义形状

0 投票
1 回答
48 浏览
提问于 2025-04-13 20:17

看起来,当你用一组坐标来指定一个乌龟的形状时,你必须先写y坐标,然后再写x坐标,但我找不到任何地方有这个说明。这是真的吗?

这是一个自定义设计的形状:

turtle_house_shape

如果我按照这里的坐标注册这个形状:

s.register_shape('house', ((-10,-10),(10,-10),(10,2),(0,12),(-4,8),
                        (-4,12),(-6,12),(-6,6),(-10,2)))

结果是这样的:

rotated_house

不仅图像顺时针旋转了90度,而且变成了镜像(烟囱在房子的另一边)。但是,如果我把每个坐标中的x和y调换位置,就会得到这个结果:

correct_house

我很困惑,为什么注册形状的代码会有这样的奇怪现象。难道文档中没有提到这一点吗?

针对ggorlen的回复:

这是代码:

from turtle import *

s = Screen()
s.setup(400,400)
s.bgcolor('lightgray')
s.register_shape('house', ((-10,-10),(10,-10),(10,2),(0,12),(-4,8),
                            (-4,12),(-6,12),(-6,6),(-10,2)))
s.register_shape('house_xy_switch', ((-10,-10),(-10,10),(2,10),(12,0,),
                            (8,-4),(12,-4),(12,-6),(6,-6),(2,-10)))

chez_moi = Turtle()
#chez_moi.shape('house')
chez_moi.shape('house_xy_switch')

在Python的乌龟图形中,y坐标是向上增加的,0,0在屏幕的中心。我的假设是,这也应该是指定乌龟自定义形状坐标的方式。

我在在线平台trinket上用Python 3.2.0进行了编码。我刚刚在IDLE中用Python 3.10.7尝试了“房子”形状,结果是顺时针旋转了90度,但不再是镜像了。所以在3.2和3.10之间,乌龟的代码肯定有一些修改。

根据cdlane的回答,编辑了更多细节

我做了另一个例子,说明为什么旋转形状90度不一定有帮助。

space_ship

这个自定义形状代表了一艘宇宙飞船。如果我想让飞船向右移动,我会把方向设置为0,让它向前移动,想让它的头朝右。

当我在Python 3.10.7中按照x坐标在前的惯例输入形状坐标时:

s.register_shape('ship', ((36, 0), (0, -12), (-32, -12), (-32, 12),
          (0, 12), (12, 8), (20, 7.6), (24, 4)))

它产生了这个输出(乌龟的默认方向是0度):

spaceship turtle

如果我让这个乌龟向前移动,它会向右移动,但却是从顶部边缘先出发(而不是头部先出发),这完全不是我想要的。如果我把方向设置为90,然后向前移动,它会向移动。解决这个问题的唯一方法就是调整形状规格中的坐标,把它们全部逆时针旋转90度(这意味着交换x和y,并且把新的x坐标的符号取反)。

我真不敢相信这就是原本的意图。

1 个回答

0

根据你最初的绘图坐标,我觉得小海龟的表现是对的。小海龟的起始方向是0度,也就是朝着X轴的正方向。所以如果我们想让房子竖起来,就需要把方向设置为90度,也就是朝着Y轴的正方向:

from turtle import Screen, Turtle

screen = Screen()

screen.register_shape('house', (
    (10, -10), (-10, -10), (-10, 2), (-6, 6),
    (-6, 12), (-4, 12), (-4, 8), (0, 12), (10, 2)
    )
)

turtle = Turtle(shape='house')
turtle.shapesize(5)

turtle.setheading(90)

screen.exitonclick()

你可以用 screen.mode("logo") 来替代 turtle.setheading(90),这样在设置 screen 时就能使用“向上是0度”的模式。不管哪种方式,我都没有看到烟囱反向的问题。

我同意小海龟的文档应该更清楚地解释这一点。(同样,shapesizestretch_* 参数在没有解释的情况下看起来也是反的。)

撰写回答