一篇文教你使用python Turtle库画出“精美碎花小清新风格树”快来拿代码!

Turtle库手册可以查询查询 python图形绘制库turtle中文开发文档及示例大全,手册中现有示例,不需要自己动手就可以查看演示。

文章修改记录

修改记录 1:2020年5月17日 12:06:51

由于某些童鞋回复说自己会卡死,请把代码:tracer(False) 改为:`tracer(200,1)`

本文已经上传了py文件在csdn下载,不过要分,源代码跟本文源码一致,不用下载,如果真的要下载我建议你还是看完文章;
下载请点击 跳转,或者直接
点击文章头部资源下载即可。
————————————————————————————————————

开始

使用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 randomdef 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 randomdef 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 randomdef 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 randomdef 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,-750yval=50for 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+=50down()      

运行如下:
在这里插入图片描述
因为我们自己定义的坐标系是 [-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 randomdef 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,-750for i in range(30):up()goto(x,y)x+=100down()yval=50for 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+=50down()      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 randomdef 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,-750for i in range(30):up()goto(x,y)x+=100down()yval=50for 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+=50down()      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()

结果如下:
在这里插入图片描述
如果觉得落叶落花不够多,可以改一下参数即可。由于代码没优化导致运行效果过慢,之后优化后再贴上来。

如果对你有帮助,点个赞加个关注呗!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/288118.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QQ,MSN,Skype在线客服代码

QQ,MSN,Skype在线客服代码 在网站建设时&#xff0c;为了更好的实施网站的营销型&#xff0c;会用到QQ&#xff0c;MSN等在线交流&#xff0c;以便客户能够快捷方便的联系我们。在这里&#xff0c;提供QQ&#xff0c;MSN的在线客服代码给大家分享&#xff1a; 1.QQ在线咨询代码…

阿里云500服务器内部错误,腾讯云服务器网站不能打开 提示内部错误http 500

满意答案2010qqww2015.11.14采纳率&#xff1a;55% 等级&#xff1a;9已帮助&#xff1a;13114人实服务器内部500错误大概可分为两种&#xff0c;一种是服务器本身权限问题&#xff0c;另一种是程序上不规范或者错误造成。所以要解决此问题需要先弄清楚其到底是哪种原因&…

物联网智能硬件设备常见攻击方法

以太网接入型设备&#xff0c;一般分为网线或WiFi两种。不管是WiFi还是网线&#xff0c;可以通过局域网抓包、笔记本WiFi桥接抓包等等手段。最著名的抓包软件 Wireshark如何抓取硬件设备的网络数据包&#xff0c;考量的是网络知识基本功&#xff0c;需要大家自行度娘&#xff0…

Hadoop(四)C#操作Hbase

HbaseHbase是一种NoSql模式的数据库&#xff0c;采用了列式存储。而采用了列存储天然具备以下优势&#xff1a;可只查涉及的列&#xff0c;且列可作为索引&#xff0c;相对高效针对某一列的聚合及其方便同一列的数据类型一致&#xff0c;方便压缩同时由于列式存储将不同列分开存…

剑指offer之两个栈实现队列问题

1 问题 两个栈实现队列的插入和获取头部元素的功能 2 分析 我们定义连个栈stack1&#xff0c;stack2&#xff0c;当队列弹出头部元素的时候&#xff0c;我们知道队列先进后出&#xff0c;我们先把一个元素压到stack1,然后再压一个元素到stack1,然后我们把stack1的top函数得到…

【ArcGIS风暴】ArcGIS 10.2导入Excel数据X、Y坐标(经纬度、平面坐标),生成Shapefile点数据图层

用过CASS的人都知道,野外数字测图得到的点数据(平面坐标)可以直接导入到CASS中,进一步绘制地形图。那么,带有坐标的数据能不能在ArcGIS中实现点图层的生成呢?答案是必须的! 本文以气象台站shp数据的生成为例,详细介绍ArcGIS 10.2中导入X、Y坐标(这里指的是经度、纬度)…

【二】Windows API 零门槛编程指南——CreateWindow 窗口创建 “万字长篇专业术语全解”

本系列博文几乎没有难啃的“专业术语”&#xff0c;尽量让读者能够看明白文章所述内容&#xff0c;是本系列博文的核心宗旨之一。&#xff08;由于本人也是由于项目需要&#xff0c;所以才来查阅相关资料&#xff0c;文中出现的错误欢迎指出&#xff0c;共同进步&#xff01;谢…

一行命令 优化上传速度

本文来自 fir.im 首席吉祥物 TraWor. 最近许多用户反映上传速度慢的一塌糊涂&#xff0c;七牛的上传带宽我想肯定是没问题的&#xff0c;那原因不必多想就剩下 DNS 了。 即便本地网络再快&#xff0c;DNS 服务器给了一个很远的服务器地址也没办法很快的上传。 在终端运行这一行…

go 服务器 源码,LollipopGo开源游戏服务器框架--global服务器源码

大家好&#xff0c;我是彬哥&#xff0c;本节给大家讲下LollipopGov1.0.20190102版本游戏服务器globla服务器&#xff0c;抛砖引玉了&#xff0c;主要是针对Go语言游戏服务器Global服务器处理。package mainimport ("LollipopGo/LollipopGo/conf""LollipopGo/Lo…

ArcGIS导入Sketchup模型

ArcGIS可以与Sketchup、3D Studio Max等三维软件完美进行交互。 ArcGIS可以借助 Import 3D Files 工具支持主流的三维模型导入。支持 3D Studio Max (*.3ds)、VRML and GeoVRML 2.0 (*.wrl)、SketchUp 6.0 (*.skp)、OpenFlight 15.8 (*.flt)、Collaborative Design Activity (C…

剑指offer之两个队列实现栈的问题

1 问题 两个队列实现栈的插入和获取头部元素的功能 2 分析 1&#xff09;获取头部元素的功能分析&#xff1a; 我们有2个队列&#xff0c;我们知道队列的特点的先进先出&#xff0c;而栈的特点是先进后出&#xff0c;比如我们有数据1,2,3,4,我们分别依次压入队列1&#xff0…

ios wkweb设置图片_iOS WKWebView (NSURLProtocol)拦截js、css,图片资源

项目地址github&#xff1a;HybirdWKWebVIewHybridNSURLProtocol一个基于WKWebView的hybirde的容器。能拦截所有WKWKWebView的的css,js,png等网络请求的demoNSURLProtocol 子类&#xff0c;就可以对 app 内所有的网络请求进行:[NSURLProtocol registerClass:[HybridNSURLProtoc…

solr的空间查询(查询地图周围坐标)

原文网址&#xff1a;http://www.cnblogs.com/hanhuibing/articles/5680616.html 基于Solr的空间搜索 如果需要对带经纬度的数据进行检索&#xff0c;比如查找当前所在位置附近1000米的酒店&#xff0c;一种简单的方法就是&#xff1a;获取数据库中的所有酒店数据&#xff0c;…

「零门槛多语言 Python/C/C# 通用思想学习系列」第一篇:经典HelloWorld

环境说明 操作系统&#xff1a;Windows7 SP1 编辑器说明&#xff1a; Python&#xff1a;notepadC&#xff1a;devcC sharp&#xff08;C#&#xff09;&#xff1a;Visual Studio2019 注意&#xff1a; 标点&#xff1a;在编程中要使用英文的标点符号&#xff0c;必须切记数…

c# 元组类型

简介元组就是将一组松散的对象简单地组合在一起。元组比数组灵活性略强&#xff0c;数组中元素类型是统一的&#xff0c;而元组使用的是泛型参数&#xff0c;每个元素类型相互独立。元组不同于类和结构&#xff0c;类和结构是高度聚合的数据类型&#xff0c;其中要实现各种复杂…

服务器2008 系统日志 提示打印机,介绍服务器日志出现打印机错误的解决方法

今天来聊聊一篇关于服务器日志出现打印机错误的解决方法的文章,现在就为大家来简单介绍下服务器日志出现打印机错误的解决方法,希望对各位小伙伴们有所帮助。windows2003日志提示&#xff0c;打印机 ****未知。登录之前&#xff0c;请与管理员联系&#xff0c;安装驱动程序。事…

js 错误/异常处理

为什么80%的码农都做不了架构师&#xff1f;>>> /*** 自定义错误处理*/ onerror handleError; function handleError(desc,page,line){alert("desc:"desc"\n""page:"page"\n""line:"line); } var s null; s.t…

多面体 (Multipatch)

多面体要素是一种可存储面集合的 GIS 对象,能够在数据库中将 3D 对象的边界表示为单个行。面可存储表示要素组成部分的纹理、颜色、透明度和几何信息。面中存储的几何信息可以是三角形、三角扇、三角条带或环,如下所示。 所有多面体都将…

剑指offer之二叉搜索树的第K个节点

1 问题 给定一颗二叉搜索树&#xff0c;请找出其中的第k小的结点。例如&#xff0c; 5 3 7 2 4 6 8 中&#xff0c;按结点数值大小顺序第三个结点的值为4。 2 分析 二叉树定义&#xff1a;二叉查找树&#xff08;Binary Search Tree&#xff09;&#xff0c;&#xff0…

Python turtle库实现基本剖析

有关turtle的相关使用请参考《python图形绘制库turtle中文开发文档及示例大全》 本篇文为turtle库的实现剖析&#xff0c;但不涉及 python 的 TK库。 开始 入口探寻 在turtle中&#xff0c;直走是使用 forward 或者 fd 函数&#xff1b;在本机安装好了 turtle 库后&#xf…