当前位置 博文首页 > 1_bit 的博客:祝CSDN2021牛气冲天祝我也拨云散雾

    1_bit 的博客:祝CSDN2021牛气冲天祝我也拨云散雾

    作者:[db:作者] 时间:2021-06-03 17:55

    前言

    2020年4月,我写了一篇用turtle绘制《小清新风格的树》,反响挺好。现在打算使用turtle修改一下绘制方式,因为线条的绘制太过考虑因素过多,如果使用方块进行堆叠,绘制出来的形状可以如马赛克一样,既符合IT,也较为建议,又方便一些低龄段的孩子学习turtle;毕竟turtle的文档上说的很清楚,turtle是为了提升青少年学习python的乐趣而开发的,那我也为这个乐趣舔一份彩吧。
    虽然这个工具由于时间关系还没写好,只实现了其中一部分,也就是核心的线条部分,代码也没优化。计划是之后打算写一个图像库,直接调用即可绘制不同种类的字母、数字、人以及各类物体。
    有始有终,既然我正式连续性的写博客是从小清新树这篇文开始,那么即将到春节,也草草的做个总结吧。

    计划

    我们先看几张马赛克风格的图片:

    我们的马赛克风格一般是由一些颜色的小方块组合而成,并且使用了阶梯式来呈现出弧度的效果,但基本元素是小方块。那么我们第一步就先绘制出一个基本小方块为core吧。

    一、绘制小方块

    我们创建一个函数为point点,以后绘制小方块都使用这个函数即可。在turtle中绘制一个正方形的小方块很简单,for循环4次left或者right,并且进行fd画线即可,新建一个文件为core,代码如下:

    from turtle import *
    
    class Core:
        def point(self):
            for i in range(0,4):
                fd(10)
                right(90)
    

    接下来我们创建一个文件为drawdemo,在其中进行测试:

    from core import Core
    
    pxtool=Core()
    pxtool.point()
    input()
    

    成功绘制:

    在此需要注意,要统一标注,以后绘制一个点都需要从这个方法进行出发。接下来开始给这个方法增加参数,这样可以动态的绘制指定大小;增加了参数后还需要有一个填充颜色,使用turtle的填充方法begin_fill与end_fill,并且需要给予颜色值fillcolor;再添加一个笔杆颜色,设置默认与填充颜色一致。我们可以创建2个方法,分别设置填充颜色与笔杆颜色:

    from turtle import *
    
    class Core:
        def point(self,plenght=10,fcolor="black",pcolor="1",psize=1):
            self.fillcolor_set(fcolor)
            self.pencolor_set(fcolor,pcolor)
            self.pensize_set(psize)
            begin_fill()
            for i in range(0,4):
                fd(plenght)
                right(90)
            end_fill()
        
        #填充颜色色值
        def fillcolor_set(self,fcolor="black"):
            fillcolor(fcolor)
        
        #笔杆颜色设置
        def pencolor_set(self,fcolor="black",pcolor="1"):
            if pcolor=="1":
                pcolor=fcolor
                pencolor(pcolor)
            else:
                pencolor(pcolor)
        
        #笔杆尺寸
        def pensize_set(self,psize=1):
            pensize(psize)
    

    这个时候就可以传值,随意的设置颜色和大小了:

    pxtool=Core()
    pxtool.point(30,fcolor="red",pcolor="blue",psize=10)
    

    二、绘制线

    我们从已有的点上开始出发,直接绘制线段线段绘制的方法很简单,也就是平移点到下一个绘制坐标进行点的绘制即可。首先我们查看绘制完一个点后的小乌龟位置:

    小乌龟回到了初始点,这个时候我们默认往右开始绘制线段,那么这个时候就应该是当前绘制向前移动一个单位,我们在这里统一不使用fd,使用goto进行跳转:

    def loc_goto(self,plenght):
           penup()
           goto(pos()+(plenght,0))
           pendown()
            
    def line(self,lenght=1,plenght=10,fcolor="black",pcolor="1",psize=1):
          for i in range(0,lenght):
               self.point(plenght=plenght,fcolor=fcolor,pcolor=pcolor,psize=psize)
               if i!=(lenght-1):
                   self.loc_goto(plenght)
    

    以上写了2个方法,一个是line绘制线,一个是跳转到下一个单位的goto方法,但是在line方法中,我们只在有需要跳转时跳转,不需要跳转时,最后一笔时则不跳转,方便之后的扩展少改动,只做有限的事情,绝不画蛇添足。
    效果如下:

    编写好向右绘制线段好我们接下来需要向左绘制线段。向左绘制线段需要使用loc_goto方法减去当前的x坐标点,向左移动即可,并且在line方法中添加参数,判断方向:

    def line(self,lenght=1,plenght=10,direction="right",fcolor="black",pcolor="1",psize=1):
            for i in range(0,lenght):
                self.point(plenght=plenght,fcolor=fcolor,pcolor=pcolor,psize=psize)
                if i!=(lenght-1):
                    if direction=="right":
                        self.loc_goto(plenght)
                    elif direction=="left":
                        self.loc_goto(-plenght)
                elif i==(lenght-1):
                    if direction=="left":
                        self.loc_goto(plenght)
    

    以上代码为了保证一个标准型,所有的绘制方法在最后一个矩形绘制时需要进行移动,所以在方向扥估left时向右移动了一个单位的距离。同理,接下来向上绘制以及向下绘制代码如下,并且修改loc_goto方法,loc_goto方法只做移动,不复再值拼接,再设置一个方法用于控制line绘制的移动:

    def loc_goto(self,movepos):
            penup()
            goto(pos()+movepos)
            pendown()
    #line方法的绘图跳转控制
    def line_func_draw_move(self,cout_i,direction,lenght,plenght):
        if cout_i!=(lenght-1):
            if direction=="right":
                self.loc_goto((plenght,0))
            elif direction=="left":
                self.loc_goto((-plenght,0))
            elif direction=="up":
                self.loc_goto((0,plenght))
            elif direction=="down":
                self.loc_goto((0,-plenght))
        elif cout_i==(lenght-1):
            if direction=="left":
                self.loc_goto((plenght,0))
            if direction=="up":
                self.loc_goto((0,-plenght))
    
    def line(self,lenght=1,plenght=10,direction="right",fcolor="black",pcolor="1",psize=1):
            for i in range(0,lenght):
                self.point(plenght=plenght,fcolor=fcolor,pcolor=pcolor,psize=psize)
                self.line_control_func_draw_move(i,direction,lenght,plenght)
    

    三、阶梯绘制

    阶梯在马赛克绘画中是当作弧来使用,阶梯有每个阶梯的长,以及每个阶梯的高;长我们可以使用横线绘制,高我们使用横线往上绘制即可完成。

    def step(self,lenght=1,height=1,blenght=1,plenght=10,direction="right",fcolor="black",pcolor="1",psize=1):
            for i in range(0,lenght):
                self.line(lenght=blenght,plenght=plenght,direction=direction,fcolor=fcolor,pcolor=pcolor,psize=psize)
                self.loc_goto((plenght,plenght))
                self.line(lenght=blenght,plenght=plenght,direction="up",fcolor=fcolor,pcolor=pcolor,psize=psize)
                if i!=(lenght-1):
                    self.loc_goto((plenght,plenght*2))
    

    以上代码绘制方法一样,首先绘制横线,然后跳转到下一个绘制点,由于要绘制成马赛克锯齿状所以跳转的位置的高度会提高一个单位self.loc_goto((plenght,plenght*2))。其中lenght是总长度,height是每个分段位的高度,blenght是每个分段的长度。意思就说lenght表示有多少个分段,blenght每个分段位有多少长度,height为每个分段的高度。代码调用:

    pxtool.step(2,2,2,10,direction="right",fcolor="red",pcolor="blue")
    

    结果如下:

    接着我们绘制起始绘制方向为左边、左下、右下的阶梯,这时只需要更改绘制时的跳转坐标以及绘制方向以及写一个控制跳转的方法即可:

    #step方法的绘图跳转控制
    #@lenght=总长
    #@blenght=bit一个位长度
    #@plenght=点长度
    #@direction1=横线绘制方向
    #@direction2=竖线绘制方向
    #@fcolor=填充颜色
    #@pcolor=笔颜色
    #@psize=笔大小
    #@gotopos=如何跳转pos位置
    #@cout_i=循环控制变量i
    def step_control_func_draw_move(self,lenght,blenght,plenght,direction1,direction2,fcolor,pcolor,psize