zoukankan      html  css  js  c++  java
  • [MoocPython课程]Turtlr库绘图之“富士山下”

    找到一个挺漂亮的图片,我们试着用python把它画出来。

    在这里插入图片描述
    打算的构图:
    1.富士山 2.花田 3.樱花树 4.樱花雨
    第一步,导入绘图库,建立画布,找准坐标,做到心中有数

    import turtle as t
    t.setup(800,600,0,0)
    

    画布中心为(0,0),左右边界(-400,400)上下边界(-300,300)
    第二步 1,填充背景色
    https://tool.oschina.net/commons?type=3
    在网络上选择一个RGB颜色对照表

    t.bgcolor('Thistle')  # 背景色
    
    	2.画富士山
    	选择富士山的颜色:深蓝色
    
    t.fillcolor('RoyalBlue3')
    t.begin_fill()
    t.seth(15)
    t.circle(800,15)
    print('雪山左标记点:',t.position())
    t.circle(800,15)
    

    在这里之所以不一次性把弧形画完,是因为想找出这个点,方便后面画山上的积雪。
    用到turtle.position()调出此刻的坐标。

    t.seth(-15)
    t.circle(250,30)
    

    这是山顶的弧线

    t.seth(-50)
    t.circle(800,15)
    print('雪山右标记点:', t.position())
    t.circle(800, 15)
    

    山右侧的弧线

    t.end_fill()
    

    结束山体颜色(深蓝色)填充
    3.画积雪

    t.fillcolor('Snow2')
    t.begin_fill()
    jumpTo(-207.06,79.92)#左标记点
    t.seth(30)
    t.circle(800, 15)#左半弧
    t.seth(-15)
    t.circle(250, 30)#上弧
    t.seth(-50) 
    t.circle(800, 15) #右弧
    t.seth(-142)
    t.circle(-350,80) #下弧
    t.end_fill()
    

    跳至刚才的标记点圈出积雪范围,填充挑选和的颜色
    3.花田,大体方法同雪山,其实比雪山更简单

    地面

    def land():
        jumpTo(-400,0)
        t.pencolor('DarkViolet')
        t.fillcolor('DarkViolet')
        t.begin_fill()
        t.goto(-400,-150)
        t.seth(0)
        t.circle(600,39.5)
        t.goto(-400,0)
        t.end_fill()
        t.pencolor('Plum')
        t.fillcolor('Plum')
        t.begin_fill()
        jumpTo(-400, 0)
        t.goto(-400, -150)
        t.seth(0)
        t.circle(600, 39.5)
        t.goto(400,-22)
        t.goto(400,-300)
        t.goto(-400,-300)
        t.goto(-400,0)
        t.end_fill()
    
    4.樱树
    

    用到了递归的思想,
    假设,只有一层树的话,(落笔,画枝,抬笔,返回),若多层的话就需要判断层树并转角度画枝。
    樱树1.0

    import turtle as t
    def tree(n):
        t.pd()
        t.fd(50)
        if n>0:
            t.right(30)
            tree(n-1)
            t.left(30+30)
            tree(n-1)
            t.right(30)
        t.pu()
        t.backward(50)
    
    t.setup(800,600,0,0)
    t.seth(90)
    tree(3)
    t.done()
    

    效果:
    在这里插入图片描述
    存在问题:

    1. 树干树枝长度相同,使樱树不够逼真,应将其设置成变量,在递归过程中长度递减
    2. 树枝偏转角度过于死板,应加入随机数使得树枝更仿生
    3. 树干树枝粗细、颜色都相同,也应改进为递减的
    4. 没有樱花,当递归至最后一层应画上樱花
      樱树2.0
    def sTree(x,y,n,l):
        jumpTo(x,y)
        t.seth(90)
        sakuraT(n,l)
    
    def sakuraT(n,l):
        t.pd()
        # 树干颜色的渐变
        tt = math.cos(math.radians(t.heading() + 45)) / 8 + 0.25
        t.pencolor(tt, tt, tt)
        t.pensize(n*2)
        # 树干粗细的渐变
        t.forward(l)
        if n>0:
            b = random.random() * 15 + 10  # 右分支偏转角度
            c = random.random() * 15 + 10  # 左分支偏转角度
            d = l * (random.random() * 0.25 + 0.7)  # 下一个树枝的长度
            t.right(b)
            sakuraT(n-1,d)
            t.left(b+c)
            sakuraT(n-1,d)
            t.right(c)
        else:
            t.right(90)
            t.pencolor('DeepPink')
            t.circle(3)
            t.left(90)
        t.pu()
        t.backward(l)
    

    效果:
    在这里插入图片描述
    5.樱花雨
    创建一个颜色列表,每场雪50个雪花,所谓雪花即画一个圈,在选定范围用随机函数random.randint()选取(x,y)的坐标,再用random.choice()从颜色列表中随机选取雪花的颜色。

    雪花

    def snow(x,y,r):
        jumpTo(x,y)
        t.circle(r)
    
    def snowS():
        colorList = ['Orchid1','Orchid2','Orchid3','Orchid4']
        for i in range(50):
            x=random.randint(-400,400)
            y=random.randint(1,300)
            r=random.randint(1,10)
            c=random.choice(colorList)
            t.pencolor(c)
            t.fillcolor(c)
            t.begin_fill()
            snow(x,y,r)
            t.end_fill()
    

    主函数:
    把画笔速度提高一些,雪花和数后画,因为再视野前面
    并且选择先画树再画雪再画树,这样更逼真

    t.speed(0)
    fjmountain()
    land()
    for i in range(2):
        sTree(random.randint(-300,300),random.randint(-300,-150),7,100)
        snowS()
    t.done()
    

    注:
    我们经常用到的跳跃函数是自己包装好的

    跳跃函数

    def jumpTo(x,y):
        t.penup()
        t.goto(x,y)
        t.pendown()
    

    最终效果:
    在这里插入图片描述
    补充:
    引发一个思考,能不能把填充颜色这个功能包装起来,然后循环一次性填充完呢?

    第一次尝试,把颜色放入colorlist列表中,函数放入functionlist列表中,然后循环

    colorList = [ 'DarkViolet','Plum','RoyalBlue3','Snow2']
    functionList = [land0(),land1(),fjmountain(),snowOnM()]
    
    for i in range(4):
        t.fillcolor(colorList[i])
        t.pencolor(colorList[i])
        t.begin_fill()
        functionList[i]
        t.end_fill()
    

    结果发现,运行代码,只画线,不填色。
    在这里插入图片描述
    问题究竟出在哪里呢?是函数不能作为对象存储在列表中吗?
    并不是的,在python中,任何对象都被认为是可以存储在列表中的
    但错就错在,列表中应该存放函数名,而不是直接function()
    加了括号,那就直接调用了,换句话说,我之前的函数都没有返回值,那列表中就是很多个空值,调用出来也没什么效果,自然无法填充,函数名不加括号(),才代表的是这个函数,加括号就是执行这个函数!!!!!
    最终改动代码如下:

    import turtle as t
    import math
    import random
    t.setup(800,600,0,0)
    # 跳跃函数
    def jumpTo(x,y):
        t.penup()
        t.goto(x,y)
        t.pendown()
    # 富士山
    def fjmountain():
        jumpTo(-400,0)
        t.seth(15)
        t.circle(800,15)
        # print('雪山左标记点:',t.position())
        t.circle(800,15)
        # print('雪山左顶点:', t.position())
        t.seth(-15)
        t.circle(250,30)
        t.seth(-50)
        t.circle(800,15)
        # print('雪山右标记点:', t.position())
        t.circle(800, 15)
        # print('雪山右顶点:', t.position())
        print(t.position())
    
    def snowOnM():
        jumpTo(-207.06, 79.92)
        t.seth(30)
        t.circle(800, 15)
        t.seth(-15)
        t.circle(250, 30)
        t.seth(-50)
        t.circle(800, 15)
        t.seth(-142)
        t.circle(-350, 80)
    
    # 雪花
    def snow(x,y,r):
        jumpTo(x,y)
        t.circle(r)
    
    def snowS():
        colorList = ['Orchid1','Orchid2','Orchid3','Orchid4']
        for i in range(50):
            x=random.randint(-400,400)
            y=random.randint(1,300)
            r=random.randint(1,10)
            c=random.choice(colorList)
            t.pencolor(c)
            t.fillcolor(c)
            t.begin_fill()
            snow(x,y,r)
            t.end_fill()
    
    def sTree(x,y,n,l):
        jumpTo(x,y)
        t.seth(90)
        sakuraT(n,l)
    
    def sakuraT(n,l):
        t.pd()
    
        # 阴影效果
        tt = math.cos(math.radians(t.heading() + 45)) / 8 + 0.25
        t.pencolor(tt, tt, tt)
        t.pensize(n*2)
        t.forward(l)
    
        if n>0:
            b = random.random() * 15 + 10  # 右分支偏转角度
            c = random.random() * 15 + 10  # 左分支偏转角度
            d = l * (random.random() * 0.25 + 0.7)  # 下一个分支的长度
            t.right(b)
            sakuraT(n-1,d)
            t.left(b+c)
            sakuraT(n-1,d)
            t.right(c)
        else:
            t.right(90)
            t.pencolor('DeepPink')
            t.circle(3)
            t.left(90)
        t.pu()
        t.backward(l)
    # 地面
    def land0():
        jumpTo(-400, 0)
        t.goto(-400, -300)
        t.goto(400,-300)
        t.goto(400, -22)
        t.goto(-400, 0)
    
    def land1():
        jumpTo(-400, 0)
        t.goto(-400, -150)
        t.seth(0)
        t.circle(600, 39.5)
        t.goto(-400, 0)
    
    t.bgcolor('Thistle')  # 背景色
    t.speed(0)
    
    colorList = [ 'DarkViolet','Plum','RoyalBlue3','Snow2']
    functionList = [land0,land1,fjmountain,snowOnM]
    
    for i in range(4):
        t.fillcolor(colorList[i])
        t.pencolor(colorList[i])
        t.begin_fill()
        functionList[i]()
        t.end_fill()
    
    
    
    
    for i in range(2):
        sTree(random.randint(-300,300),random.randint(-300,-150),7,100)
        snowS()
        pass
    t.done()
    
  • 相关阅读:
    python--异常处理
    Codeforces 1499D
    Codeforces 1263E
    Codeforces 1493D
    Codeforces 1492D
    Codeforces 1490G
    Codeforces 1487E
    Codeforces 1485D
    Codeforces 1485C
    P6917 [ICPC2016 WF]Balanced Diet
  • 原文地址:https://www.cnblogs.com/hzshisan/p/12571084.html
Copyright © 2011-2022 走看看