目标图像
设计思路
分别封装两个主要函数ground(),mkSweat();
(1)*ground()*:画出背景的黄色笑脸,分别使用circle()函数画圆和使用for循环随角度变化改变半径画出椭圆。
(2)用*for循环*反复调用*mkSweat()*并改变参数:实现流汗的动画效果
涉及的turtle()库函数及功能
函数 | 功能 |
---|---|
speed() | 笔的移动速度参数范围0.5——10,范围之外为0,最快,不设置速度为最慢 |
delay() | 用于返回或设置绘制延迟(以毫秒为单位)。它只需要一个可选的参数作为延迟一个正整数。 |
pensize() | 设置画笔尺寸,单位为像素 |
pencolor() | 设置画笔颜色 |
hideturtle() | 隐藏画笔 |
screensize() | 设置画布的长、宽、以及bgcolor |
fillcolor() | 设置填充颜色 |
begin_fill() | 开始填充 |
circle() | 画圆填充 |
end_fill() | 填充结束 |
pu() | 抬起笔,停止写 |
goto() | 笔移动到坐标(x,y) |
pd() | 放下笔,开始写 |
color() | color(colorstring1, colorstring2), color((r1,g1,b1), (r2,g2,b2))等效于pencolor(colorstring1)和fillcolor(colorstring2) 类似地使用其他输入格式。 |
seth() | 设置笔的朝向,画笔默认朝向为正右方 |
update() | 一般和tracer()搭配使用,刷新画面,图画在后台内存中画好,然后执行刷新命令时,将内存读取到画面窗口中。 |
tracer() | 参数设置为false时省略作画过程 |
reset() | 删除画的内容,还原画笔参数为初始值 |
forward() | 向前写,参数为像素数值 |
backward | 向后写,参数为像素数值 |
right() | 向右写,参数为像素数值 |
left() | 向左写,参数为像素数值 |
done() | 关闭turtle,一般在使用完turtle后添加,否则会无响应 |
设计的两个函数及其功能
ground()
1.设置一些基础参数pensize()\hideturtle()\screenszie()
画出最下层的橘色边缘('#E69138')和黄色底色('#f1c232')
t.pensize(8)
t.pencolor('#E69138')
t.hideturtle()
t.screensize(500, 500, bg='white')
t.fillcolor('#f1c232')
t.begin_fill()
t.circle(120)
t.end_fill()
# 画出底色
2.为了画出微笑的嘴角,首先画一个褐色正圆,再用和底色相同的椭圆做恰当的覆盖,实现嘴角弯弯的效果
t.pu()
t.goto(-70, 70)
t.pd()
t.color('#80542b', '#9e6430')
t.pensize(6)
t.seth(-60)
t.begin_fill()
t.circle(80)
t.end_fill()
# 画出嘴角的褐色圆
a = 2.8
t.pu()
t.goto(90, 160)
t.seth(90)
t.pensize(4)
t.pd()
t.color('#f1c232')
t.begin_fill()
for i in range(120):
if 0 <= i < 30 or 60 <= i < 90:
a = a + 0.1
t.lt(3) # 向左转3度
t.fd(a) # 向前走a的步长
else:
a = a - 0.1
t.lt(3)
t.fd(a)
t.end_fill()
# 画完微笑的嘴角
到这一步的实现效果:
3.画出笑眼,和上一步的原理相同,通过与黄色同色的部分区域覆盖得到笑眼的形状
a = 0.4
t.seth(0)
t.pensize(3)
t.pu()
t.goto(-37, 110)
t.pensize(4)
t.pd()
t.color('#80542b', '#9e6430')
t.begin_fill()
a = 0.32
for i in range(120):
if 0 <= i < 30 or 60 <= i < 90:
a = a + 0.064
t.lt(3)
t.fd(a)
else:
a = a - 0.064
t.lt(3)
t.fd(a)
t.end_fill()
t.pu()
t.goto(37, 110)
t.pensize(4)
t.pd()
t.color('#80542b', '#9e6430')
t.begin_fill()
for i in range(120):
if 0 <= i < 30 or 60 <= i < 90:
a = a + 0.064
t.lt(3) # 向左转3度
t.fd(a) # 向前走a的步长
else:
a = a - 0.064
t.lt(3)
t.fd(a)
t.end_fill()
# 画完褐色椭圆
t.pensize(3)
t.pu()
t.goto(-35, 89)
t.pensize(4)
t.pd()
t.color('#f1c232')
t.begin_fill()
a = 0.3
for i in range(120):
if 0 <= i < 30 or 60 <= i < 90:
a = a + 0.06
t.lt(3)
t.fd(a)
else:
a = a - 0.06
t.lt(3)
t.fd(a)
t.end_fill()
t.pu()
t.goto(35, 89)
t.pensize(4)
t.pd()
t.color('#f1c232')
t.begin_fill()
for i in range(120):
if 0 <= i < 30 or 60 <= i < 90:
a = a + 0.06
t.lt(3) # 向左转3度
t.fd(a) # 向前走a的步长
else:
a = a - 0.06
t.lt(3)
t.fd(a)
t.end_fill()
# 画完眼睛
4.画出牙齿
a = 3.05
t.pu()
t.goto(-70, 94)
t.seth(315)
t.pd()
t.pencolor('white')
t.pensize(12)
for i in range(30):
if 0 <= i < 15:
a = a + 0.25
t.lt(3) # 向左转3度
t.fd(a) # 向前走a的步长
else:
a = a - 0.25
t.lt(3)
t.fd(a)
# 牙齿的代码
t.update()
函数调用完后的实现效果
mkSweat()
汗滴的实现是将两个形状相同,大小和颜色不同的汗滴图形进行部分重叠,实现阴影的效果,汗滴形状通过圆和等腰三角形拼接而成
def mkSweat(x):
t.tracer(False)
#省去作画过程,直接显示图形
t.reset()
ground()
# 开始记录多边形的顶点。当前的乌龟位置是多边形的第一个顶点。
t.pu()
t.goto(76, x)
t.pd()
t.seth(0)
t.color('#289df8')
t.pensize(6)
t.begin_fill()
t.circle(20)
t.end_fill()
#
t.pu()
t.goto(56, x + 20)
t.pd()
t.seth(0)
t.color('#289df8')
t.pensize(6)
t.begin_fill()
t.forward(40) # 根据正前方角度画线
t.right(75) # 画笔向右旋转
t.backward(77.194) # 根据正后方角度画线
t.right(30) # 画笔向右旋转
t.fd(77.294)
t.end_fill()
#
t.pu()
t.goto(78, x)
t.pd()
t.seth(0)
t.color('#00ffff')
t.pensize(6)
t.begin_fill()
t.circle(15.8)
t.end_fill()
#
t.pu()
t.goto(59, x + 18)
t.pd()
t.seth(0)
t.color('#00ffff')
t.pensize(1)
t.begin_fill()
t.forward(36) # 根据正前方角度画线
t.right(75) # 画笔向右旋转
t.backward(69.565) # 根据正后方角度画线
t.right(30) # 画笔向右旋转
t.fd(69.565)
t.end_fill()
t.hideturtle()
time.sleep(0.1)
遇到问题及解决思路
在整个绘图过程中确实遇到了不少问题
(1)绘图过程缓慢
只是改变speed()的参数还不够,于是通过上网查阅资料,将delay()的参数设置为0,得到了满意的绘图速度。
(2)汗滴的动态绘图问题
一开始想象的ground()和mkSweat()是两个相互独立的模块,但是后来发现如果不在mkSweat()的开头进行图像清空,无法得到想要的效果,于是采用了绘完一帧,清空一次画布,在mkSweat()里面调用一次ground(),并且将tracer()的参数设置为false,立即得到绘图结果,得到干净的动画效果。
(3)绘画结果的保留问题
没有想到的是,只要函数调用结束,绘画结果并不会呈现在画布上,必须使用update()进行更新,通过网络上查阅资料解决了这一问题。
最终运行结果
编程心得体会
turtle是在我开始学习python以来,除了RPi.GPIO和matplotlib以外的第三个亲密接触的 库,明白了一个道理:进行python库学习的最好方法永远是进行相关的项目实践,纸上谈兵的学习方法显然不行。
在整个实验的完成过程中,常常有调参数到崩溃的时刻,靠着耐心和有始有终的信念,最后还是完成了自己心心念念的成果。有过被室友“大可不必”的劝退时刻,但是为了自己的一点幽默和固执,还是坚持了下来。
turtle()也许不会成为我以后常用的库,但是这次又愉快的经历,也许以后工作多年后也不会忘记。
“流汗黄豆”是我大学时代的网络烙印,这就是我选择它作为素材的原因。