一篇文教你使用python Turtle库画出“精美碎花小清新风格树”快来拿代码!
Turtle库手册可以查询查询 python图形绘制库turtle中文开发文档及示例大全,手册中现有示例,不需要自己动手就可以查看演示。
使用Turtle画树,看了一下网上的代码,基本上核心的方法是使用递归;其次通过递归传参更笔的粗细从而改变绘制时的线段,更改树的躯干大小,在遍历到最后一个节点时,更改笔的颜色及粗细,绘制出树尖的花瓣或绿叶。
本篇博文使用的是网上的代码修改而成的,基本上写来写出简单编写也是使用递归,我也就拿过来用了。本来想顺便把环境也绘制一遍,但是明天上班了,今天还有别的事,就只能作罢,有时间再写一篇把环境都弄好的案例吧;下面是最终代码运行后的结果(代码没优化,效率可能不是很好):
感觉有点小清新,哈哈哈,故意配的色,碎花系!
好了,现在开始看看怎么写吧,最终代码在最下面,上面是一步步讲解其中遇见的一些问题。
首先我们使用最简单的方式绘制树的一条躯干,代码如下:
from turtle import * left(80)
fd(100)
right(30)
fd(30)
right(30)
fd(40)
input()
结果如下:
以上代码首先使用t.left(80)
让turtle转到几乎垂直于水平线位置,随后使用t.fd(100)
往剪头所指的方向绘制100个单位的线段,随后t.right(30)
向右转向30度,再t.fd(30)
往前绘制30个单位的线段;这个时候线段之间有了一个节点,这个节点就是通过right转动角度后产生的,模拟树的躯干;最后t.right(30)
再向右转向30度,t.fd(40)
往前绘制40个单位长度线段,使最后的躯干得到延伸。
不过以上的线段并不适合形容树这个植物,不过别急,我们先更改一下绘制的线段粗细,和颜色,让绘制的图片看起来更像树。
color|pensize()
通过t.pensize()
、t.color()
更改笔的粗细与颜色,代码如下:
from turtle import * color('#5E5E5E')
pensize(10)
left(80)
fd(100)
right(30)
fd(30)
right(30)
fd(40)
input()
更改好笔的粗细后,绘制的结果如下:
可能结果更像是一根草,不过没关系,我们慢慢更改代码;现在我们加长一下树的枝干和缩小一下笔的粗细:
from turtle import * color('#5E5E5E')
pensize(6)
left(80)
fd(150)
right(30)
fd(50)
right(30)
fd(60)
input()
结果如下:
看起来好了很多,整个树干部分可以分为主要的躯干以及散开的枝条,我们通过可以分为几个部分编写;首先绘制树的主干,随后使用函数绘制树的枝条:
from turtle import * def drawTree(length):
right(20)
fd(length) color('#5E5E5E')
pensize(5) up()
goto(0,-300)#跳到绘制起始点
down() left(80)
fd(140)
drawTree(60)
input()
运行结果如下:
此时代码从最绘制区域最下方开始往上绘制,使用 color('#5E5E5E')
设置了绘制颜色;pensize(5)
设置了绘制的线段粗细;goto(0,-300)
跳转到了绘制区域的下半部分做为起笔点;随后向左转动80度,画一根线段作为树的主干;之后调用函数 drawTree(120)
传入长度进行枝条的绘制,在drawTree
函数中,right(20)
向右侧转动了20度,fd(length)
画一条线段作为枝条。
既然写了函数,那我们就可以使用递归开始进行枝条的绘制了:
from turtle import * def drawTree(length):
if length>1:
right(20)
fd(length)
drawTree(length - 10) color('#5E5E5E')
pensize(5) up()
goto(0,-300)#跳到绘制起始点
down() left(80)
fd(140)
drawTree(60)
input()
运行结果如下:
从代码上看,只修改了 drawTree 函数部分的代码内容;在函数中使用了递归,递归后传入的值为当前长度减10个长度,并且函数中判断,长度大于1的时候才执行,这样就防止了递归中没有跳出条件而产生的死循环。
现在的长度都是有有固定差值的,使用随机数使绘制的枝条长度随机,更加贴近真实枝条的情况(在此只贴出修改部分的代码):
def drawTree(length):
if length>1:
right(20)
fd(length)
randlen=random.random()
drawTree(length - 10*randlen)
运行结果:
代码使用了随机数,随机值与固定差值10进行相减,得到值后参与减法运算。
那么在这里,旋转角度也是固定的,我们再把旋转角度给随机一下:
def drawTree(length):
if length>1:
randangle=random.random()
randlen=random.random()
right(20*randangle)
fd(length) drawTree(length - 10*randlen)
运行结果:
正式开始
我们的枝条现在只有一个方向,那就是往右,我们现在添加向左的枝条绘制:
from turtle import *
import random def drawTree(length):
if length>1:
randangle=random.random()
randlen=random.random()
right(20*randangle)
fd(length) drawTree(length - 10*randlen)
left(40 * randangle)
fd(length) color('#5E5E5E')
pensize(5) up()
goto(0,-300)#跳到绘制起始点
down() left(80)
fd(140)
drawTree(60)
input()
然而出错了:
为什么会这样?
那是因为我们需要跳转到上一个绘制的位置,使用 backward 函数就可以了,改动 drawTree 函数如下:
def drawTree(length):
if length>1:
randangle=random.random()
randlen=random.random()
right(20*randangle)
fd(length)
up()
backward(length)
down()
left(40 * randangle)
fd(length)
drawTree(length - 10*randlen)
结果如下:
其实这个效果还是不错,不过并不是我们想要的,这个效果可能画狗尾巴草不错;更改一下代码:
from turtle import *
import random def drawTree(length):
if length>1:
#随机角度与长度
randangle=random.random()
randlen=random.random() #每次使用函数先绘制线段,再调整角度,这里是向右的角度转动
fd(length)
right(20*randangle)
drawTree(length - 10*randlen) #这里是向左的角度转动
left(40 * randangle)
drawTree(length - 10*randlen) #为什么需要再向右转20度?那是因为我一共向左转了40度,使用backward后退,必须是相同的角度,不然退回去角度就不同了位置就不会对
right(20 * randangle) up()
backward(length)
down() tracer(False)
color('#5E5E5E')
pensize(5) up()
goto(0,-300)#跳到绘制起始点
down() left(80)
fd(140)
drawTree(60)
input()
结果如下:
代码解释在注释里,就是个简单的递归,但是由于传入的 length 长度并不长,导致枝条绘制的线段不是很多,会导致整棵树长的不够茂盛,我们修改一下 length 传入值,改为120,绘制结果如下,注意,由于绘制过久,直接使用 tracer(False) 可以直接显示效果,就没必要绘制一次渲染一下了(这个得看你参数,直接改为False即可);在此要更改坐标系,自定义为比现在更大的坐标系,不然屏幕显示不全的,使用代码setworldcoordinates(-1000,-750,1000,750)
即可,整体代码如下:
from turtle import *
import random def drawTree(length):
if length>1:
#随机角度与长度
randangle=random.random()
randlen=random.random() #每次使用函数先绘制线段,再调整角度,这里是向右的角度转动
fd(length)
right(20*randangle)
drawTree(length - 10*randlen) #这里是向左的角度转动
left(40 * randangle)
drawTree(length - 10*randlen) #为什么需要再向右转20度?那是因为我一共向左转了40度,使用backward后退,必须是相同的角度,不然退回去角度就不同了位置就不会对
right(20 * randangle) up()
backward(length)
down() setworldcoordinates(-1000,-750,1000,750)
tracer(False)
color('#5E5E5E')
pensize(5) up()
goto(0,-300)#跳到绘制起始点
down() left(80)
fd(140)
drawTree(120)
input()
结果如下:
但是由于随机数的转角和枝条长度没有限制最低的长度,可以在随机的时候给一个合适的数字相乘,并且把起笔位置再往下调,代码如下:
randangle=2*random.random()
randlen=2*random.random()
.
.
.
.
.
.
goto(0,-700)
结果如下:
差不多完成了
一棵树的大致形状绘制好了,现在开始,把树的枝条的绿色和红花填上;一般来说,树的枝条越顶端,那么越小,判断长度这个值,在一定范围内是绿色,一定范围内是红色,那么就可以模拟出树开花和树绿叶的效果了,代码如下,其中的颜色代码,可以自己去调整:
from turtle import *
import random def drawTree(length):
if length>1:
if length<30 and length>14:#缩小一下树干
pensize(4)
elif length<15 and length>5:#长度这个范围内那么就是绿叶
color('#04B486')#
pensize(3)
elif length<5 and length>1:#红花
color('#FE2E9A')
pensize(2)
else:
color('#5E5E5E')#其他范围就是正常的树干
pensize(5)
#随机角度与长度
randangle=2*random.random()
randlen=2*random.random() #每次使用函数先绘制线段,再调整角度,这里是向右的角度转动
fd(length)
right(20*randangle)
drawTree(length - 10*randlen) #这里是向左的角度转动
left(40 * randangle)
drawTree(length - 10*randlen) #为什么需要再向右转20度?那是因为我一共向左转了40度,使用backward后退,必须是相同的角度,不然退回去角度就不同了位置就不会对
right(20 * randangle) up()
backward(length)
down() setworldcoordinates(-1000,-750,1000,750)
tracer(False)
color('#5E5E5E')
pensize(5) up()
goto(0,-700)#跳到绘制起始点
down() left(80)
fd(140)
drawTree(120)
input()
运行结果如下:
绘制落花
树有点长的茂盛,哈哈哈;每次随机都是不一样的树形,所以我也不懂它会一个屏幕显示不下,不过关系不大,我们现在开始绘制落叶落花效果。
落花效果的函数如下:
def fallingFlowers(m):
x,y=-1000,-750 yval=50
for i in range(m):
a = 100*random.random()
b = 2*random.random()
print(a)
if a>59:
color('#FE2E9A')
else:
color('#04B486')
circle(5)
up()
goto(x,y+(yval*b))
fd(a)
yval+=50
down()
运行如下:
因为我们自己定义的坐标系是 [-1000,-750]到[1000,750],我们就从左下角的位置开始进行落花的绘制,在代码中定义了x和y坐标的值是 x,y=-1000,-750
,随后循环里面使用一个y值进行每次的增加,每次绘制的位置从左下角往上走,所以y坐标每次循环都增加,并且赋予随机相乘,这样就会更好的进行随机了,每次都使用goto(x,y+yval)
跳转到指定的x,y坐标位置,但是在这里要注意,x的值是不变的;并且在循环里我设置了一个a变量,这个变量a主要是用作fd(a)进行x轴上的随机,相同的值就会导致相同的排列,不是很美观,同样随机值b与yval相乘的原因也是这个。
再修改代码,在外层套个循环,使x坐标值相加,横向的铺满绘制区域:
from turtle import *
import random def drawTree(length):
if length>1:
if length<30 and length>14:#缩小一下树干
pensize(4)
elif length<15 and length>5:#长度这个范围内那么就是绿叶
color('#04B486')#
pensize(3)
elif length<5 and length>1:#红花
color('#FE2E9A')
pensize(2)
else:
color('#5E5E5E')#其他范围就是正常的树干
pensize(5)
#随机角度与长度
randangle=2*random.random()
randlen=2*random.random() #每次使用函数先绘制线段,再调整角度,这里是向右的角度转动
fd(length)
right(20*randangle)
drawTree(length - 10*randlen) #这里是向左的角度转动
left(40 * randangle)
drawTree(length - 10*randlen) #为什么需要再向右转20度?那是因为我一共向左转了40度,使用backward后退,必须是相同的角度,不然退回去角度就不同了位置就不会对
right(20 * randangle) up()
backward(length)
down()
def fallingFlowers(m):
x,y=-1000,-750
for i in range(30):
up()
goto(x,y)
x+=100
down()
yval=50
for i in range(m):
a = 100*random.random()
b = 2*random.random()
print(a)
if a>59:
color('#FE2E9A')
else:
color('#04B486')
circle(5)
up()
goto(x,y+(yval*b))
fd(a)
yval+=50
down() setworldcoordinates(-1000,-750,1000,750)
tracer(False)
color('#5E5E5E')
pensize(5) # up()
# goto(0,-700)#跳到绘制起始点
# down() # left(80)
# fd(140)
# drawTree(120)
fallingFlowers(10)
input()
运行结果:
新增的外层循环使x的值递增,最后平铺满绘制区域下半部分。
最终结果
最后结合树的绘制代码,打开注释,并且设置一下背景色bgcolor("#F5F6CE")
:
from turtle import *
import random def drawTree(length):
if length>1:
if length<30 and length>14:#缩小一下树干
pensize(4)
elif length<15 and length>5:#长度这个范围内那么就是绿叶
color('#04B486')#
pensize(3)
elif length<5 and length>1:#红花
color('#FE2E9A')
pensize(2)
else:
color('#5E5E5E')#其他范围就是正常的树干
pensize(5)
#随机角度与长度
randangle=2*random.random()
randlen=2*random.random() #每次使用函数先绘制线段,再调整角度,这里是向右的角度转动
fd(length)
right(20*randangle)
drawTree(length - 10*randlen) #这里是向左的角度转动
left(40 * randangle)
drawTree(length - 10*randlen) #为什么需要再向右转20度?那是因为我一共向左转了40度,使用backward后退,必须是相同的角度,不然退回去角度就不同了位置就不会对
right(20 * randangle) up()
backward(length)
down()
def fallingFlowers(m):
x,y=-1000,-750
for i in range(30):
up()
goto(x,y)
x+=100
down()
yval=50
for i in range(m):
a = 100*random.random()
b = 2*random.random()
print(a)
if a>59:
color('#FE2E9A')
else:
color('#04B486')
circle(5)
up()
goto(x,y+(yval*b))
fd(a)
yval+=50
down() setworldcoordinates(-1000,-750,1000,750)
tracer(False) fallingFlowers(10)#绘制落叶
bgcolor("#F5F6CE")
color('#5E5E5E')
pensize(5) up()
goto(0,-700)#跳到绘制起始点
down() left(80)
fd(140)
drawTree(120) input()
结果如下:
如果觉得落叶落花不够多,可以改一下参数即可。由于代码没优化导致运行效果过慢,之后优化后再贴上来。
如果对你有帮助,点个赞加个关注呗!
一篇文教你使用python Turtle库画出“精美碎花小清新风格树”快来拿代码!的更多相关文章
- 课程作业——Python基础之使用turtle库画出红旗
代码如下: import turtle # 设置画笔和背景颜色 turtle.color('yellow') turtle.bgcolor('red') # 通过偏移量和尺寸大小画星星 def dra ...
- 用Turtle库画一个爱心
---恢复内容开始--- 用Python中的turtle库画一个爱心 这个学期,我学了Python语言,并学到其中的一个库:turtle库.用turtle库可以画一些你想画的图片,所以我就想画一个爱心 ...
- Python turtle库详解
Python turtle库详解 Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x.纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在 ...
- Python Turtle库绘制蟒蛇
使用Python Turtle库来绘制蟒蛇 import turtle引入了海龟绘图体系 使用setup函数,设定了一个宽650像素和高350像素的窗体,其位置左上角坐标是200,200 说明位置在距 ...
- Python turtle库的画笔控制说明
turtle.penup() 别名 turtle.pu() :抬起画笔海龟在飞行 turtle.pendown() 别名 turtle.pd():画笔落下,海龟在爬行 turtle.pensize(w ...
- Python语言程序设计之二--用turtle库画围棋棋盘和正、余弦函数图形
这篇笔记依然是在做<Python语言程序设计>第5章循环的习题.其中有两类问题需要记录下来. 第一是如何画围棋棋盘.围棋棋盘共有19纵19横.其中,位于(0,0)的星位叫天元,其余8个星位 ...
- python turtle库
turtle库初步 先看 https://www.cnblogs.com/chy8/p/9448606.html 一 turtle库介绍 turtle乌龟 import turtle from tur ...
- Python turtle库学习笔记
1.简介 Python的turtle库的易操作,对初学者十分友好.对于初学者来说,刚学编程没多久可以写出许多有趣的可视化东西,这是对学习编程极大的鼓舞,可以树立对编程学习的信心.当然turtle本身也 ...
- 第1课(续集),python turtle库的使用
原文再续,书接上一回 上回讲到了,python IDLE的草稿本和作业本,并顺便试了试python的输入输出,变量,运算的体验,大家应该能感受到python的简单了吧. 下面我们继续体验python的 ...
随机推荐
- JavaScript HTMlL DOM对象(上)
Dom:document.相当于把所有的html文件,转换成了文档对象. 之前说过:html-裸体的人:css-穿上衣服:js-让人动起来. 让人动起来,就得先找到他,再修改它内容或属性. 找到标签 ...
- vue项目中上拉加载和下拉刷新页面的实现
功能:上拉加载,下拉刷新 使用方法: 自己创建一个.vue的文件(我自己是创建了一个PullToRefresh.vue的文件),将代码粘贴进去,具体的样式问题自己在该文件中调整. <templa ...
- mysql备份及恢复
第四章:MySQL数据库的备份与恢复 2016-09-30 00:58:05 标签:数据库备份 工作原理 数据库表 mysql source 原创 ...
- CodeForces - 1102A(思维题)
https://vjudge.net/problem/2135388/origin Describe You are given an integer sequence 1,2,-,n. You ha ...
- Effective C++学习记录
Effective C++算是看完了,但是并没有完全理解,也做不到记住所有,在此记录下55个条款及条款末的"请记住". 让自己习惯C++ 条款01:视C++为一个语言联邦 ① C ...
- Nginx模块开发(3)————使用upstream访问第三方服务
该模块可以完成如下的功能,当我们输入http://你的ip/lcwupstream时,会使用upstream方式访问淘宝搜索,打开淘宝搜索的主页面,代码如下: //start from the ver ...
- Unity 游戏框架搭建 2019 (四十四、四十五) 关于知识库的小结&独立的方法和独立的类
在上一篇,我们完成了一个定时功能,并且接触了 Action 和委托.lambda 表达式这些概念. 到目前为止,我们的库作为知识收录这个功能来说,已经非常好用了,由于使用了 partial 关键字,所 ...
- jQuery中bind()与on()绑定事件的区别
.on()方法比.bind()方法多一个参数selector .on()的selector参数是筛选出调用.on()方法的dom元素的指定子元素,如: $("ul").on('cl ...
- Cookie什么?Cookie和Session防御怎么做?
Cookie什么?Cookie和Session防御怎么做? Cookie的概念 Cookie,复数形态Cookies,中文名称为小型文本文件.指某些网站为了辨别用户身份.进行session跟踪而储存在 ...
- dumpsys-package
dumpsys-package ams和pms是android系统最重要的系统服务,本文解析dumpsys package命令,看哪些PMS相关的系统信息,数据结构是运行时可以查看的. 命令提示 co ...