情人节绘制爱心最合适了,但是单单画一个心形怎么能够满足?今天我们尝试用Python的turtle库画出一整个画布的爱心,让它们在上面动态移动。最终效果如下:

爱心python代码 爱心python代码turtle_爱心python代码

绘制爱心

画爱心有很多种画法,我这里用的方法是用两个圆形和一个正方形组成爱心。而且为了接下来能够实现上百个爱心比较流畅地移动的效果,这里直接用三个画笔组成一个爱心,执行速度会更快。代码如下:

from turtle import *
from math import sqrt
width, height = 800, 600
screen = Screen()     # 创建窗口对象
screen.setup(width, height)    # 设置窗口的宽高
screen.delay(0)    # 设置无延时绘画
screen.bgcolor('pink')     # 设置背景颜色为粉色

# 设置画笔的统一属性
t = Turtle(visible=False, shape='circle')
t.shapesize(10, 10)
t.pencolor('red')
t.fillcolor('red')
t.penup()
# 克隆一个圆形,设置位置
circle1 = t.clone()
circle1.goto(-sqrt(10*10*160)/2, 0)
# 克隆第二个圆形,设置位置
circle2 = t.clone()
circle2.goto(sqrt(10*10*160)/2, 0)
# 克隆一个正方形,设置位置并旋转角度
square = t.clone()
square.shape("square")
square.setheading(45)
square.goto(0, -sqrt(10*10*160)/2)
# 显示图形
circle1.showturtle()
circle2.showturtle()
square.showturtle()
done()

效果图如下:

爱心python代码 爱心python代码turtle_指定位置_02



定义爱心类

接着,我们将这种画法的爱心定义为一个类。这样后面要显示多个爱心并调整它们的位置会比较方便。将上面的代码稍作修改,成为下面的代码:

class Heart:
    def __init__(self, x, y, size):
        self.size = size    # 心形大小
        self.speed = size    # 移动速度根据大小变化
        t = Turtle(visible=False, shape='circle')
        t.shapesize(size, size)
        color = (1, 1- size/4, 1-size/4)     # 颜色修改为根据大小变化的粉色
        t.pencolor(color)
        t.fillcolor(color)
        t.penup()
        self.circle1 = t.clone()
        self.circle1.goto(x-sqrt(size*size*160)/2, y)
        self.circle2 = t.clone()
        self.circle2.goto(x+sqrt(size*size*160)/2, y)
        self.square = t.clone()
        self.square.shape("square")
        self.square.setheading(45)
        self.square.goto(x, y-sqrt(size * size * 160)/2)
        self.circle1.showturtle()
        self.circle2.showturtle()
        self.square.showturtle()

代码里定义了爱心的移动速度和颜色与大小相关:爱心越大,颜色越深,移动速度越快。这样表现出来的效果会更加丰富。

在主函数里随机生成25个位置和大小不同的爱心,并存入列表:

hearts = []
for i in range(25):
    heart = Heart(width/2 + randint(1, width), randint(-height/2,height/2), random()*3)
    hearts.append(heart)



让爱心动起来

在爱心类中定义一个方法(函数)move(),用来让爱心向左移动一个单位速度长度:

def move(self):
        self.circle1.setx(self.circle1.xcor()-self.speed)
        self.square.setx(self.square.xcor() - self.speed)
        self.circle2.setx(self.circle2.xcor() - self.speed)

然后在主函数里面写一个死循环,让所有爱心重复不断的移动:

while True:
    for heart in hearts:
        heart.move()

添加完这两处代码后,爱心就可以动起来了:

爱心python代码 爱心python代码turtle_ide_03


让爱心回到起点

此时还有一个问题没处理,爱心从屏幕左侧出去后就没有新的爱心了。其实我们并不需要新的爱心,只需要把从左边出去的爱心再偷偷移动回右侧起点就行。

定义一个将爱心移动到指定位置的方法(函数)moveTo(x, y)

def moveTo(self, x, y):
        # 隐藏形状后再移动防止看到移动轨迹
        self.circle1.hideturtle()
        self.circle2.hideturtle()
        self.square.hideturtle()
        # 移动到指定位置
        self.circle1.goto(x - sqrt(self.size * self.size * 160) / 2, y)
        self.circle2.goto(x + sqrt(self.size * self.size * 160) / 2, y)
        self.square.goto(x, y - sqrt(self.size * self.size * 160) / 2)
        # 恢复显示
        self.circle1.showturtle()
        self.circle2.showturtle()
        self.square.showturtle()

接着在循环中用 if 语句判断,当爱心位置移动出屏幕左侧时,将其移动到右侧随机位置:

while True:
    for heart in hearts:
        heart.move()
        if heart.square.xcor() < -width / 2:     # 如果爱心移动出屏幕左侧
            heart.moveTo(width / 2 + randint(1, width), randint(-height / 2, height / 2))   # 回到右侧随机位置

到这里,完整的效果就完成了。不过turtle没法实现全屏效果,爱心只能填满画布,有点可惜。

爱心python代码 爱心python代码turtle_爱心python代码