python库turtle的双画笔并发绘制兔兔 表白神器

这篇博客通过Python的turtle库和多线程技术,同时绘制两只兔子,背景中伴有樱花树和雪花的分形几何图案。使用互斥锁确保绘制同步,展现了分形几何的自相似性和迭代思想。代码中包含樱花树、科赫雪花的绘制函数,以及黑白兔子的详细绘制过程,创造出丰富的视觉效果。

使用python中的turtle库同时画两只兔兔,方法是创建多线程。

设置双画笔

(调用的函数放在最后面)

y = turtle.Pen()    # 绘制左边的画笔
d = turtle.Pen()    # 绘制右边的画笔

turtle.bgcolor(0.5, 0.5, 0.5)  # 背景色
turtle.screensize(1800, 1000)  # 画布尺寸
turtle.hideturtle()  # 隐藏画笔
# y._tracer(0, 0)  # 如果不想看动画直接看结果,把注释去掉

t1 = threading.Thread(target=white_rabbit)
t2 = threading.Thread(target=black_rabbit)
t1.start()
t2.start()

turtle.exitonclick()

此篇只贴图形函数代码,整个程序完整效果图:
在这里插入图片描述

动画效果是先画完树和雪花,再草地雪地,然后两只兔子,每一步都创建两个线程使两边并发绘制,最后加上中间爱心。因为在每个环节中某一边可能会更快画完,所以要用到两个互斥锁,控制一支画笔等另一只画完,保证下个环节依旧同时进行。这里用兔子绘制函数做演示:

mutex1 = threading.Lock()
mutex2 = threading.Lock()
def white_rabbit():
	mutex1.acquire()    # 上第一把锁
	...
	mutex2.release()    # 解第二把锁
def black_rabbit():
	mutex2.acquire()    # 上第二把锁
	...
	mutex1.release()    # 解第一把锁

樱花树和雪花都属于分型几何,分形是描述复杂几何形体结构的一种数学概念。分形几何的特点是:客观事物具有自相似的层次结构。在设计算法中主要运用的是迭代思想。

樱花树绘制函数

    def cherry(self, n, len):
        '''
        樱花二叉树
        :param n: 树迭代层数
        :param len: 树枝长度
        :return:
        '''
        y.pd()
        # 阴影效果
        t = cos(radians(y.heading() + 45)) / 8 + 0.25
        y.pencolor(t, t, t)
        y.pensize(n / 3)
        y.forward(len)  # 画树枝
        if n > 0:
            b = random() * 15 + 10  # 右分支偏转角度
            c = random() * 15 + 10  # 左分支偏转角度
            d = len * (random() * 0.25 + 0.7)  # 下一个分支的长度
            y.right(b)  # 右转一定角度,画右分支
            self.cherry(n - 1, d)
            y.left(b + c)   # 左转一定角度,画左分支
            self.cherry(n - 1, d)
            y.right(c)   # 转回来
        else:
            # 画叶子
            y.right(90)
            n = cos(radians(y.heading() - 45)) / 4 + 0.5
            y.pencolor(n, n * 0.8, n * 0.8)
            y.circle(3)
            y.left(90)
            # 添加0.3倍的飘落叶子
            if (random() > 0.7):
                y.pu()
                # 飘落
                t = y.heading()
                an = -40 + random() * 40
                y.setheading(an)
                dis = int(800 * random() * 0.5 + 400 * random() * 0.3 + 200 * random() * 0.2)
                y.forward(dis)
                y.setheading(t)
                # 画叶子
                y.pd()
                y.right(90)
                n = cos(radians(y.heading() - 45)) / 4 + 0.5
                y.pencolor(n * 0.5 + 0.5, 0.4 + n * 0.4, 0.4 + n * 0.4)
                y.circle(2)
                y.left(90)
                y.pu()
                # 返回
                t = y.heading()
                y.setheading(an)
                y.backward(dis)
                y.setheading(t)
        y.pu()
        y.backward(len)

    def draw_cherry(self):
        y.pu()
        y.goto(-520, -380)
        y.seth(0)
        y.left(90)
        y.pd()
        y.pensize(4)
        y.pencolor('black')
        y.forward(80)
        y.pu()
        self.cherry(12, 100)

科赫雪花绘制函数

def Koch_curve(self, n, len):
    '''
    科赫曲线(三分之一的雪花)
    :param n: 分形次数
    :param len: 一段线段长度
    :return:
    '''
    if n == 0:
        d.forward(len)
    else:
        for i in [0, 60, -120, 60]:
            d.left(i)
            self.Koch_curve(n-1, len/3)

def Koch_snowflake(self, n, len):
# 循环三次科赫曲线得到雪花
    for a in range(3):
        self.Koch_curve(n, len)
        d.right(120)

def draw_snowflake(self):
# 画了三朵雪花
    d.pensize(2)
    d.color('white')
    d.pu()
    d.goto(300, 100)
    d.pd()
    self.Koch_snowflake(5, 400)
    d.pu()
    d.goto(100, 300)
    d.pd()
    self.Koch_snowflake(4, 200)
    d.pu()
    d.goto(700, 400)
    d.pd()
    self.Koch_snowflake(3, 100)

黑白兔绘制函数

RADIUS = 50
ANGLE = 50
W_X = -200
W_Y = -340
B_X = 200
B_Y = -340

def white_rabbit():
    y.hideturtle()
    y.speed(4)
    y.pensize(3)
    # 头部
    y.color('white')
    y.pu()
    y.goto(W_X, W_Y)
    y.seth(0)
    y.pd()
    y.begin_fill()
    y.circle(RADIUS, 360)
    y.end_fill()
    # 耳朵
    y.pu()
    y.goto(RADIUS * sin(2 * ANGLE) + W_X, RADIUS * cos(2 * ANGLE) + RADIUS + W_Y)
    y.pd()
    y.seth(120)
    y.begin_fill()
    y.circle(-50, 60)
    y.circle(-10, 120)
    y.circle(-50, 55)
    y.pu()
    y.seth(0)
    y.forward(15)
    y.pd()
    y.seth(120)
    y.circle(-50, 55)
    y.circle(-10, 120)
    y.circle(-50, 62)
    y.end_fill()
    # 眼睛
    y.color('red')
    y.pu()
    y.seth(0)
    y.goto(-RADIUS * sin(ANGLE) + W_X, RADIUS + W_Y)
    y.pd()
    y.begin_fill()
    y.circle(5)
    y.pu()
    y.forward(2 * RADIUS * sin(ANGLE))
    y.pd()
    y.circle(-5)
    y.end_fill()
    # 身体
    y.color('white')
    y.pu()
    y.seth(0)
    y.goto(-RADIUS * sin(ANGLE) + 10 + W_X, 10 + W_Y)
    y.seth(-50)
    y.pd()
    y.begin_fill()
    y.circle(-130, 30)  # 1
    y.circle(-12, 140)  # 2
    y.circle(160, 40)  # 3
    y.circle(50, 75)  # 5
    y.circle(-10, 140)  # 6
    y.circle(-100, 45)  # 7
    # 尾巴
    y.seth(0)
    y.circle(10)
    # 背部
    y.seth(25)
    y.circle(-160, 35)
    y.end_fill()
    # 前腿
    y.pu()
    y.goto(W_X, -42 + W_Y)
    y.pd()
    y.seth(-130)
    y.begin_fill()
    y.fd(25)
    y.circle(-8, 110)
    y.fd(40)
    y.end_fill()
    # 后腿
    y.pu()
    y.goto(-145 + W_X, -50 + W_Y)
    y.pd()
    y.seth(-95)
    y.begin_fill()
    y.fd(15)
    y.circle(5, 150)
    y.fd(3)
    y.end_fill()

def black_rabbit():
    d.hideturtle()
    d.speed(4)
    d.pensize(3)
    # 头部
    d.color('black')
    d.pu()
    d.goto(B_X, B_Y)
    d.pd()
    d.begin_fill()
    d.circle(RADIUS, 360)
    d.end_fill()
    # 耳朵
    d.pu()
    d.goto(RADIUS * sin(2 * ANGLE) + B_X, RADIUS * cos(2 * ANGLE) + RADIUS + B_Y)
    d.pd()
    d.seth(120)
    d.begin_fill()
    d.circle(-50, 60)
    d.circle(-10, 120)
    d.circle(-50, 55)
    d.pu()
    d.seth(0)
    d.forward(15)
    d.pd()
    d.seth(120)
    d.circle(-50, 55)
    d.circle(-10, 120)
    d.circle(-50, 62)
    d.end_fill()
    # 眼睛
    d.color('red')
    d.pu()
    d.seth(0)
    d.goto(RADIUS * sin(ANGLE) + B_X, RADIUS + B_Y)
    d.pd()
    d.begin_fill()
    d.circle(-5)
    d.pu()
    d.forward(2 * RADIUS * sin(ANGLE))
    d.pd()
    d.circle(5)
    d.end_fill()
    # 身体
    d.color('black')
    d.pu()
    d.seth(0)
    d.goto(RADIUS * sin(ANGLE) - 10 + B_X, 10 + B_Y)
    d.seth(-130)
    d.pd()
    d.begin_fill()
    d.circle(130, 30)  # 1
    d.circle(12, 140)  # 2
    d.circle(-160, 40)  # 3
    d.circle(-50, 75)  # 5
    d.circle(10, 140)  # 6
    d.circle(100, 45)  # 7
    # 尾巴
    d.seth(0)
    d.circle(10)
    # 背部
    d.seth(155)
    d.circle(160, 35)
    d.end_fill()
    # 前腿
    d.pu()
    d.goto(B_X, -42 + B_Y)
    d.pd()
    d.seth(-50)
    d.begin_fill()
    d.fd(25)
    d.circle(8, 110)
    d.fd(40)
    d.end_fill()
    # 后腿
    d.pu()
    d.goto(145 + B_X, -50 + B_Y)
    d.pd()
    d.seth(-85)
    d.begin_fill()
    d.fd(15)
    d.circle(-5, 150)
    d.fd(3)
    d.end_fill()

草地绘制函数

def ground():
    for i in range(100):
        y.pensize(randint(6, 12))
        x_zhou = randint(-SCREEN_LENGTH / 2, 0)
        y_zhou = randint(-SCREEN_WIDTH / 2, -SCREEN_WIDTH / 2 + 100)
        g = -y_zhou / 1000    # 颜色随y轴变幻
        y.pencolor(0, g, 0)
        y.pu()
        y.goto(x_zhou, y_zhou)
        y.pd()
        y.seth(0)
        y.left(randint(80, 100))
        y.forward(randint(10, 20))

雪地绘制函数

def snowfield():
    for i in range(150):
        d.pensize(randint(10, 18))
        x_zhou = randint(0, SCREEN_LENGTH / 2)
        y_zhou = randint(-SCREEN_WIDTH / 2, -SCREEN_WIDTH / 2 + 100)
        d.pencolor('white')
        d.pu()
        d.goto(x_zhou, y_zhou)
        d.pd()
        d.seth(0)
        d.forward(randint(20, 50))

爱心绘制函数

def heart_shaped(self):
# 画笔名叫love
    love.speed(2)
    love.pu()
    love.goto(-20, -100)
    love.seth(-90)
    love.pd()
    love.begin_fill()
    love.left(135)
    love.right(90)
    love.forward(50)
    love.left(90)
    love.forward(50)
    love.left(45)
    love.circle(17.67, 180)
    love.left(180)
    love.circle(17.67, 180)
    love.end_fill()
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值