python turtle作品——春节

最近尝试用turtle写的作品,发出来供大家参考

主题:春节

特色:采用先进和完备的面向对象编程,继承并重写了turtle的画笔的部分功能以将其可面向对象化。素材复用方便,代码逻辑清晰明了,函数名称遵循大小驼峰规则,语意清晰。 制备了可复用的turtle轮子和debug tools,可以在开发阶段使用鼠标进行简单的绘画以加速作品制作。 使用分文件的项目,方便管理与查看

技术要点:类、对象、继承、重载、模块化思想

作品本身较为简单,但模块化设计为turtle设计了一个轮子,对于重写的函数已经放在Base里面了(其实base也可以继承turtle,但是并没有这么设计)

对于鼠标便捷操作,左键设定第一个点,然后一直左键,最后以右键提笔,提笔状态再次右键可以回到第一个点,中间的福字就是这么描出来的(让我用turtle自行设计一个福字还是饶了我吧)。

以下文件,类名即为文件名。

 main.py:

import turtle

import Banner
import Fu
import Lantern

if __name__ == '__main__':
    """初始化turtle"""
    turtle.setup(1280, 1024)  # bba785
    turtle.screensize(bg="#f2dcbb")
    """是否开启debug,不开启debug会导致绘画速度巨慢"""
    debug = False
    """鼠标绘画,画福字用的,仅限测试"""
    # draw = TurtleTool.MouseDraw(0, 0)
    # tool = TurtleTool.Tool()
    # tool.printMouseDraw(draw)
    """杂项测试,已过时"""
    # square = Test.TestSquare(0, 260, 280, -100, size=0.6)
    # square.draw()
    """对联和横批,顺序是上联-下联-横批"""
    banner1 = Banner.Banner(260, -150, "一元复始龙增岁", rotate=-90, size=0.6, debug=debug)
    banner1.draw()
    banner2 = Banner.Banner(-260, -150, "万象生辉燕报春", rotate=-90, size=0.6, debug=debug)
    banner2.draw()
    banner = Banner.Banner(0, 230, "龙凤呈祥", rotate=180, size=0.8, debug=debug)
    banner.draw()
    """灯笼,小灯笼在for里面,两个大灯笼在for外面,只需要改变参数即可调整"""
    Lantern.Lantern(-300, 500, size=1, length=60, debug=debug).draw()
    for i in range(3):
        Lantern.Lantern(-140 + i * 140, 500, size=0.8, debug=debug).draw()
    Lantern.Lantern(300, 500, size=1, length=60, debug=debug).draw()
    """福字"""
    fu = Fu.Fu(0, -60, rotate=180, size=0.3, debug=debug)  # 对于“大门上不能贴倒福”的问题,将rotate改为0即可解决。
    fu.draw()
    """主循环"""
    turtle.mainloop()
import turtle

import TurtleBasicDraw


class Lantern(TurtleBasicDraw.BaseDraw):

    def __init__(self, x, y, length=40, size=1.0, widthSize=4, rotate=0, mainColor="#ba932a", debug=False):
        super().__init__(x, y, size, widthSize, rotate, mainColor, debug)
        #  length:灯绳的长度, must > 20
        if length < 20:
            raise ValueError
        self.length = length
        # self.relocate(0,-20-10-80) # 中心对齐方案,不是我需要的
        self.relocate(0, length - 20)  # 绳头对齐方案,正是我需要的

    def draw(self):
        super().draw()
        self.drawLine(0, self.length - 20, 0, -20)
        if not self.debug:
            # 灯笼头
            turtle.fillcolor("#f9d800")
            turtle.begin_fill()
            self.drawLine(-30, -30, -30, -20)
            self.setpos(30, -20)
            self.setpos(30, -30)
            self.setpos(-30, -30)
            turtle.end_fill()
        # 灯笼框架
        turtle.fillcolor("#fb3949")
        turtle.begin_fill()
        self.drawLine(-60, -30, 60, -30)
        self.setpos(60, -180)
        self.setpos(-60, -180)
        self.setpos(-60, -30)
        turtle.end_fill()
        if self.debug:
            return
        # 三条内部线
        self.drawLine(-30, -30, -30, -180)
        self.drawLine(0, -30, 0, -180)
        self.drawLine(30, -30, 30, -180)
        # 灯笼尾
        turtle.fillcolor("#f9d800")
        turtle.begin_fill()
        self.drawLine(-30, -180, -30, -190)
        self.setpos(30, -190)
        self.setpos(30, -180)
        self.setpos(-30, -180)
        turtle.end_fill()

        self.drawLine(-30, -190, -30, -230)
        self.drawLine(-15, -190, -15, -230)
        self.drawLine(0, -190, 0, -230)
        self.drawLine(15, -190, 15, -230)
        self.drawLine(30, -190, 30, -230)
        # self.setpos(250, 0)
import TurtleBasicDraw
import turtle


class Fu(TurtleBasicDraw.BaseDraw):
    """福字来源是TurtleBasicDraw.MouseDraw的输出,类似于ps中钢笔的使用。"""
    def __init__(self, x, y, size=1.0, widthSize=1, rotate=0, mainColor="black", debug=False):
        super().__init__(x, y, size, widthSize, rotate, mainColor, debug)
    def drawWordOut(self):
        #  扣出透明区域
        turtle.fillcolor("#d60d17")
        turtle.begin_fill()
        turtle.penup()
        self.setpos(24.0, 32.0)
        turtle.pendown()
        self.setpos(33.0, 45.0)
        self.setpos(47.0, 51.0)
        self.setpos(51.0, 43.0)
        self.setpos(43.0, 33.0)
        self.setpos(28.0, 29.0)
        self.setpos(24.0, 32.0)
        turtle.penup()

        turtle.end_fill()
        turtle.begin_fill()

        turtle.penup()
        self.setpos(15.0, -12.0)
        turtle.pendown()
        self.setpos(27.0, -7.0)
        self.setpos(40.0, -0.0)
        self.setpos(57.0, -0.0)
        self.setpos(66.0, -6.0)
        self.setpos(18.0, -12.0)
        self.setpos(15.0, -12.0)
        turtle.penup()

        turtle.end_fill()
        turtle.begin_fill()

        turtle.penup()
        self.setpos(5.0, -54.0)
        turtle.pendown()
        self.setpos(9.0, -48.0)
        self.setpos(13.0, -47.0)
        self.setpos(19.0, -51.0)
        self.setpos(11.0, -58.0)
        self.setpos(3.0, -57.0)
        self.setpos(5.0, -54.0)
        turtle.penup()

        turtle.end_fill()
        turtle.begin_fill()

        turtle.penup()
        self.setpos(11.0, -94.0)
        turtle.pendown()
        self.setpos(16.0, -89.0)
        self.setpos(24.0, -94.0)
        self.setpos(15.0, -102.0)
        self.setpos(11.0, -93.0)
        self.setpos(11.0, -94.0)
        turtle.penup()

        turtle.end_fill()
        turtle.begin_fill()

        turtle.penup()
        self.setpos(72.0, -49.0)
        turtle.pendown()
        self.setpos(69.0, -46.0)
        self.setpos(69.0, -41.0)
        self.setpos(77.0, -43.0)
        self.setpos(84.0, -43.0)
        self.setpos(91.0, -45.0)
        self.setpos(97.0, -46.0)
        self.setpos(97.0, -56.0)
        self.setpos(73.0, -50.0)
        self.setpos(72.0, -49.0)
        turtle.penup()

        turtle.end_fill()
        turtle.begin_fill()

        turtle.penup()
        self.setpos(56.0, -89.0)
        turtle.pendown()
        self.setpos(86.0, -77.0)
        self.setpos(81.0, -94.0)
        self.setpos(64.0, -97.0)
        self.setpos(57.0, -90.0)
        self.setpos(56.0, -89.0)
        turtle.penup()

        turtle.end_fill()
    def drawWord(self):
        turtle.pencolor("#fcb15e")
        turtle.fillcolor(self.mainColor)
        turtle.begin_fill()
        turtle.penup()
        self.setpos(-59.0, 152.0)
        turtle.pendown()
        self.setpos(-59.0, 158.0)
        self.setpos(-63.0, 165.0)
        self.setpos(-80.0, 160.0)
        self.setpos(-94.0, 151.0)
        self.setpos(-110.0, 137.0)
        self.setpos(-120.0, 118.0)
        self.setpos(-119.0, 95.0)
        self.setpos(-111.0, 80.0)
        self.setpos(-103.0, 67.0)
        self.setpos(-120.0, 45.0)
        self.setpos(-137.0, 32.0)
        self.setpos(-152.0, 12.0)
        self.setpos(-150.0, -7.0)
        self.setpos(-141.0, -23.0)
        self.setpos(-134.0, -26.0)
        self.setpos(-120.0, -26.0)
        self.setpos(-114.0, -25.0)
        self.setpos(-132.0, -43.0)
        self.setpos(-145.0, -56.0)
        self.setpos(-153.0, -79.0)
        self.setpos(-147.0, -91.0)
        self.setpos(-139.0, -102.0)
        self.setpos(-126.0, -113.0)
        self.setpos(-113.0, -116.0)
        self.setpos(-106.0, -113.0)
        self.setpos(-99.0, -110.0)
        self.setpos(-97.0, -127.0)
        self.setpos(-93.0, -140.0)
        self.setpos(-87.0, -148.0)
        self.setpos(-79.0, -155.0)
        self.setpos(-70.0, -157.0)
        self.setpos(-53.0, -155.0)
        self.setpos(-41.0, -147.0)
        self.setpos(-34.0, -135.0)
        self.setpos(-37.0, -120.0)
        self.setpos(-41.0, -102.0)
        self.setpos(-49.0, -76.0)
        self.setpos(-48.0, -46.0)
        self.setpos(-43.0, -20.0)
        self.setpos(-33.0, 7.0)
        self.setpos(-24.0, 13.0)
        self.setpos(-14.0, -8.0)
        self.setpos(-28.0, -6.0)
        self.setpos(-41.0, -26.0)
        self.setpos(-50.0, -53.0)
        self.setpos(-47.0, -86.0)
        self.setpos(-33.0, -131.0)
        self.setpos(-12.0, -145.0)
        self.setpos(28.0, -139.0)
        self.setpos(47.0, -139.0)
        self.setpos(57.0, -157.0)
        self.setpos(90.0, -161.0)
        self.setpos(120.0, -141.0)
        self.setpos(143.0, -88.0)
        self.setpos(151.0, -61.0)
        self.setpos(153.0, -29.0)
        self.setpos(132.0, -7.0)
        self.setpos(115.0, 3.0)
        self.setpos(98.0, 8.0)
        self.setpos(107.0, 36.0)
        self.setpos(117.0, 46.0)
        self.setpos(109.0, 60.0)
        self.setpos(103.0, 78.0)
        self.setpos(85.0, 84.0)
        self.setpos(27.0, 73.0)
        self.setpos(116.0, 97.0)
        self.setpos(120.0, 127.0)
        self.setpos(112.0, 141.0)
        self.setpos(101.0, 153.0)
        self.setpos(63.0, 153.0)
        self.setpos(26.0, 144.0)
        self.setpos(-6.0, 133.0)
        self.setpos(-14.0, 121.0)
        self.setpos(-15.0, 99.0)
        self.setpos(2.0, 86.0)
        self.setpos(5.0, 82.0)
        self.setpos(-19.0, 68.0)

        self.setpos(-29.0, 45.0)
        self.setpos(-44.0, 61.0)
        self.setpos(-76.0, 57.0)
        self.setpos(-103.0, 44.0)
        self.setpos(-76.0, 57.0)
        self.setpos(-44.0, 61.0)
        self.setpos(-25.0, 63.0)
        self.setpos(-14.0, 83.0)
        self.setpos(-12.0, 100.0)
        self.setpos(-18.0, 123.0)
        self.setpos(-37.0, 143.0)
        self.setpos(-57.0, 151.0)
        self.setpos(-58.0, 159.0)
        self.setpos(-59.0, 152.0)
        turtle.penup()
        turtle.end_fill()
        self.drawWordOut()

    def draw(self):
        super().draw()
        # 外壳
        turtle.pencolor("#d60d17")
        turtle.fillcolor("#d60d17")
        turtle.begin_fill()
        self.drawLine(0, 350, -350, 0)
        self.setpos(0, -350)
        self.setpos(350, 0)
        self.setpos(0, 350)
        turtle.end_fill()
        if self.debug:
            return
        # 内边
        turtle.pencolor("#fcb15e")
        turtle.penup()
        self.setpos(0, 325)
        turtle.pendown()
        self.setpos(-325, 0)
        self.setpos(0, -325)
        self.setpos(325, 0)
        self.setpos(0, 325)

        self.drawWord()
import turtle

import TurtleBasicDraw


class BannerSide(TurtleBasicDraw.BaseDraw):

    def __init__(self, x, y, size=1.0, widthSize=3, rotate=0, mainColor="#ba932a", debug=False):
        super().__init__(x, y, size, widthSize, rotate, mainColor, debug)

    def draw(self):
        super().draw()
        # 上半圆
        turtle.fillcolor("#e37e14")
        turtle.begin_fill()
        self.drawLine(10, -10, -10, -10)
        self.setheading(90)
        self.circle(-10, extent=180)
        turtle.end_fill()
        # 下半圆
        self.drawLine(-10, -10, -10, -110)
        turtle.begin_fill()
        self.setheading(-90)
        self.circle(10, extent=180)
        self.setpos(-10, -110)
        turtle.end_fill()
        # 卷轴
        turtle.fillcolor("#ffce31")
        turtle.begin_fill()
        self.drawLine(-10, -10, 10, -10)
        self.setpos(10, -110)
        self.setpos(-10, -110)
        self.setpos(-10, -10)
        turtle.end_fill()
        turtle.fillcolor("#fd4043")
        turtle.begin_fill()
        self.drawLine(-10, -20, 10, -20)
        self.setpos(10, -100)
        self.setpos(-10, -100)
        self.setpos(-10, -20)
        turtle.end_fill()


class Banner(TurtleBasicDraw.BaseDraw):
    def __init__(self, x, y, word, size=1.0, widthSize=4, rotate=0, mainColor="black", debug=False):
        super().__init__(x, y, size, widthSize, rotate, mainColor, debug)
        self.relocate(0,-60)
        self.word = word
        self.posX = 100 * (len(self.word) / 2) + 50
        pos1 = self.getpos(-self.posX - 10, 0)
        pos2 = self.getpos(self.posX + 10, 0)
        self.bs1 = BannerSide(pos1[0], pos1[1], size, widthSize, rotate, mainColor)
        self.bs2 = BannerSide(pos2[0], pos2[1], size, widthSize, rotate, mainColor)

    def draw(self):
        # r = 10
        # length = 10+10+200+10+10
        # height = 10+100+10
        super().draw()
        if not self.debug:
            self.bs1.draw()
            self.bs2.draw()
        posX = self.posX
        # 中间部分
        turtle.fillcolor("#ffce31")
        turtle.begin_fill()
        self.drawLine(-posX, -10, posX, -10)
        self.setpos(posX, -110)
        self.setpos(-posX, -110)
        self.setpos(-posX, -10)
        turtle.end_fill()
        if self.debug:
            return
        turtle.fillcolor("#fd4043")
        turtle.begin_fill()
        self.drawSquare(-posX, -20, posX, -100)  # 方便多了
        turtle.end_fill()
        # 字样 (注意,字底边对齐,这是坑点。
        turtle.penup()
        turtle.pencolor(self.mainColor)
        self.setpos(-posX + 100, -60)  # 第一个字正中央 需要适应turtle的中心底部对齐
        for w in self.word:
            turtle.setheading(-90)  # 强制向下,因为turtle的中心底部对齐
            self.forward(50)  # 移动到中心底部对齐位置
            self.write(w, align="center", font=("华文行楷", 55, "normal"))  # write不需要pendown,up的时候移速更快。
            self.back(50)  # 回到中心
            self.setheading(0)  # 旋转适应 向前,准备下一个字
            self.forward(100)
import math
import turtle


class BaseDraw:
    """
        智能对象,允许根据size和rotate算出真实的位置
    """

    def __init__(self, x, y, size=1.0, widthSize=4, rotate=0, mainColor="#ba932a", debug=False):
        self.x = x
        self.y = y
        self.size = size
        self.rotate = rotate
        self.widthSize = widthSize  # 画笔尺寸缩放倍率
        self.mainColor = mainColor  # 对于部分复杂图案,mainColor可能不会被使用,仅供参考。
        self.debug = debug

    def relocate(self, offsetX, offsetY):
        """
        根据所传入的内容倒推出自身的定位,属于取巧操作
        :param offsetX: 自身中心点距离自身零点的距离X
        :param offsetY: 自身中心点距离自身零点的距离Y
        :return:
        """
        pos = self.getpos(-offsetX, -offsetY)
        self.x = pos[0]
        self.y = pos[1]

    def forward(self, length):
        turtle.forward(length * self.size)

    def back(self, length):
        turtle.back(length * self.size)

    # def sety(self,offsetY):
    #     nowPos = turtle.pos()
    #     nowX = nowPos[0]
    #     nowY = nowPos[1]
    #     offsetX =
    #     turtle.setpos(self.x )
    def getpos(self, offsetX, offsetY):
        return (self.x +
                offsetX * self.size * math.cos(math.radians(self.rotate)) -
                offsetY * self.size * math.sin(math.radians(self.rotate)),
                self.y +
                offsetY * self.size * math.cos(math.radians(self.rotate)) +
                offsetX * self.size * math.sin(math.radians(self.rotate)))

    def setpos(self, offsetX, offsetY):
        pos = self.getpos(offsetX, offsetY)
        turtle.setpos(pos[0], pos[1])

    def setheading(self, to_angle):
        turtle.setheading(self.rotate + to_angle)

    def circle(self, radius, extent=None):
        turtle.circle(radius * self.size, extent)

    def draw(self):
        turtle.penup()
        self.setpos(0, 0)
        turtle.width(self.widthSize)
        turtle.color(self.mainColor)
        turtle.left(self.rotate)
        turtle.pendown()

    def drawLine(self, offsetX1, offsetY1, offsetX2, offsetY2):
        turtle.penup()
        self.setpos(offsetX1, offsetY1)
        turtle.pendown()
        self.setpos(offsetX2, offsetY2)

    def drawSquare(self, offsetX1, offsetY1, offsetX2, offsetY2):
        # 方便的画出一个方形,我怎么才想到呢
        # 提供两个对角的顶点。
        self.drawLine(offsetX1, offsetY1, offsetX2, offsetY1)
        self.setpos(offsetX2, offsetY2)
        self.setpos(offsetX1, offsetY2)
        self.setpos(offsetX1, offsetY1)

    def write(self, arg: object, move: bool = False, align: str = "left",
              font: tuple[str, int, str] = ("Arial", 8, "normal")) -> None:
        font1 = (font[0], int(font[1] * self.size), font[2])
        turtle.write(arg, move, align, font1)


class Ellipse(BaseDraw):
    def __init__(self, x, y, a, b, size=1.0, widthSize=2, rotate=0, mainColor="#ba932a", n=100):
        super().__init__(x, y, size, widthSize, rotate, mainColor)
        self.a = a
        self.b = b
        self.n = n

    def draw(self):
        super().draw()
        a = self.a / self.size
        b = self.b / self.size
        turtle.penup()
        self.setpos(a, 0)
        turtle.pendown()
        for i in range(self.n):  # i == per n
            radian = 2 * math.pi / self.n  # l = 2pi(弧度制)
            theta = (i + 1) * radian  # 下一个坐标弧度
            self.setpos(a * math.cos(theta), b * math.sin(theta))

↑这个文件除外↑,文件名是TurtleBaseDraw.py

import turtle

import TurtleBasicDraw


class MouseDraw(TurtleBasicDraw.BaseDraw):
    penDown = False
    startPos = (0, 0)

    def __init__(self, x, y, size=1.0, widthSize=4, rotate=0, mainColor="#ba932a", debug=False):
        super().__init__(x, y, size, widthSize, rotate, mainColor, debug)

    def mouseLeftClickCallBack(self, x, y):
        if not self.penDown:
            self.draw()
            payload = "turtle.penup()"
            print(payload)
            eval(payload)
            self.startPos = (x, y)
            # self.penDown = False
        payload = "self.setpos({}, {})".format(x, y)
        print(payload)
        eval(payload)
        if not self.penDown:
            payload = "turtle.pendown()"
            print(payload)
            eval(payload)
            self.penDown = True

    def mouseRightClickCallBack(self, x, y):
        if self.penDown:
            payload = "turtle.penup()"
            print(payload)
            eval(payload)
            self.penDown = False
        else:
            payload = "self.setpos({}, {})".format(self.startPos[0], self.startPos[1])
            print(payload)
            eval(payload)
            payload = "turtle.penup()"
            print(payload)
class Tool:
    def printMouseDraw(self, draw: MouseDraw):
        turtle.Screen().onclick(draw.mouseLeftClickCallBack)
        turtle.Screen().onclick(draw.mouseRightClickCallBack, 3)

鼠标工具,挺好用的,只可惜等到我画福了才想起来这个操作

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一些Python Turtle的创意作品: 1. 绘制彩色螺旋线:使用Python Turtle绘制不同颜色的线条,创建一个漂亮的彩色螺旋图案。 ``` import turtle import random turtle.speed(0) turtle.bgcolor('black') colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'] for i in range(150): turtle.color(random.choice(colors)) turtle.pensize(i/10 + 1) turtle.forward(i) turtle.left(59) ``` 2. 绘制海龟赛跑游戏:使用Python Turtle创建一个简单的海龟赛跑游戏,让玩家控制一个小海龟,尽可能快地穿过障碍物。 ``` import turtle import random # Set up the screen screen = turtle.Screen() screen.setup(500, 500) screen.title("Turtle Race") # Create the turtles turtles = [] colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'] for i in range(6): turtle = turtle.Turtle() turtle.shape('turtle') turtle.color(colors[i]) turtle.penup() turtle.goto(-230, 200 - i*50) turtles.append(turtle) # Create the finish line finish = turtle.Turtle() finish.penup() finish.goto(230, 200) finish.pendown() finish.goto(230, -200) # Start the race while True: for turtle in turtles: turtle.forward(random.randint(1, 5)) if turtle.xcor() >= 230: winner = turtle.color()[0] print("The winner is", winner) turtle.goto(-100, 0) turtle.write("Winner!", font=("Arial", 16, "bold")) break ``` 3. 绘制谢尔宾斯基三角形:使用Python Turtle绘制一个谢尔宾斯基三角形,这是一个典型的分形图形。 ``` import turtle def draw_triangle(points, color, turtle): turtle.fillcolor(color) turtle.up() turtle.goto(points[0][0], points[0][1]) turtle.down() turtle.begin_fill() turtle.goto(points[1][0], points[1][1]) turtle.goto(points[2][0], points[2][1]) turtle.goto(points[0][0], points[0][1]) turtle.end_fill() def get_mid(p1, p2): return ((p1[0]+p2[0])/2, (p1[1]+p2[1])/2) def sierpinski(points, degree, turtle): colormap = ['blue', 'red', 'green', 'white', 'yellow', 'violet', 'orange'] draw_triangle(points, colormap[degree], turtle) if degree > 0: sierpinski([points[0], get_mid(points[0], points[1]), get_mid(points[0], points[2])], degree-1, turtle) sierpinski([points[1], get_mid(points[0], points[1]), get_mid(points[1], points[2])], degree-1, turtle) sierpinski([points[2], get_mid(points[2], points[1]), get_mid(points[0], points[2])], degree-1, turtle) turtle.setup(500, 500) turtle.title("Sierpinski Triangle") my_turtle = turtle.Turtle() my_turtle.speed(0) my_points = [[-200, -100], [0, 200], [200, -100]] sierpinski(my_points, 3, my_turtle) turtle.done() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值