我想用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()
因此,如您所见,如果您运行代码,则第一个工程图是确定的,具有水平形状。但是当我在Turtle t1
上盖章时,形状是垂直的。
通过polyNotOk
定义的第二个形状有相同的问题(x和y坐标值允许获得水平桨叶)。我需要创建一个“垂直”多边形以获取水平桨。
因此,我能够找到一种解决方法。但是,我仍然对这种解决方案不满意,因此我想提出出色的解释;-)预先感谢。
答案 0 :(得分:1)
我希望阐明这种奇怪的行为,而不是捍卫它。关于绘制的光标,要记住的第一件事是,(0, 0)
落在光标绘图中的任何位置,这就是光标旋转的中心点,并且光标中的像素落在goto()
的任何点上。 / p>
在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()
类的错误,而是埋在游标逻辑中。这可能是历史的人工产物-如果我们更改为mode("logo")
并运行您的代码,则会得到:
鉴于“徽标”模式的默认方向为北,并且比以前更一致,因此我们可以期望的更多。
无论如何,我都会用不同的方式来制作桨。我会使用乌龟的 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 Invader型游戏非常有用。