Fundamentals 15 min read

Drawing a Birthday Cake with Python Turtle Graphics

This tutorial explains how to recreate a hand‑drawn birthday cake using Python's turtle library, covering the motivation, step‑by‑step code implementation with parametric equations, visual results, and reflections on code quality and potential improvements.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Drawing a Birthday Cake with Python Turtle Graphics

The author was inspired by a hand‑drawn cake seen on Bilibili and decided to recreate it programmatically using Python's turtle graphics library.

The script imports turtle , math , and random , defines helper functions drawX and drawY to compute parametric coordinates, configures the drawing canvas, and then draws a series of layered shapes with various fill colors to form a stylized cake, adds random decorative dots, and writes a "Happy Birthday" message.

<code>import turtle as t
import math as m
import random as r

def drawX(a, i):
    angle = m.radians(i)
    return a * m.cos(angle)

def drawY(b, i):
    angle = m.radians(i)
    return b * m.sin(angle)
# 设置背景颜色,窗口位置以及大小
t.bgcolor("#d3dae8")
t.setup(1000, 800)
t.penup()
t.goto(150, 0)
t.pendown()
# 1
t.pencolor("white")
t.begin_fill()
for i in range(360):
    x = drawX(150, i)
    y = drawY(60, i)
    t.goto(x, y)
    t.fillcolor("#fef5f7")
    t.end_fill()
# 2
t.begin_fill()
for i in range(180):
    x = drawX(150, -i)
    y = drawY(70, -i)
    t.goto(x, y)
for i in range(180, 360):
    x = drawX(150, i)
    y = drawY(60, i)
    t.goto(x, y)
    t.fillcolor("#f2d7dd")
    t.end_fill()
# 3
t.pu()
 t.goto(120, 0)
 t.pd()
 t.begin_fill()
for i in range(360):
    x = drawX(120, i)
    y = drawY(48, i)
    t.goto(x, y)
    t.fillcolor("#cbd9f9")
    t.end_fill()
# 4
t.begin_fill()
 t.pencolor("#fee48c")
 for i in range(540):
    x = drawX(120, i)
    y = drawY(48, i) + 70
    t.goto(x, y)
 t.goto(-120, 0)
 t.fillcolor("#cbd9f9")
 t.end_fill()
# 5
t.pu()
 t.goto(120, 70)
 t.pd()
 t.pencolor("#fff0f3")
 t.begin_fill()
 for i in range(360):
    x = drawX(120, i)
    y = drawY(48, i) + 70
    t.goto(x, y)
    t.fillcolor("#fff0f3")
    t.end_fill()
# 6
t.pu()
 t.goto(110, 70)
 t.pd()
 t.pencolor("#fff9fb")
 t.begin_fill()
 for i in range(360):
    x = drawX(110, i)
    y = drawY(44, i) + 70
    t.goto(x, y)
    t.fillcolor("#fff9fb")
    t.end_fill()
# 7
t.pu()
 t.goto(120, 0)
 t.pd()
 t.begin_fill()
 t.pencolor("#ffa79d")
 for i in range(180):
    x = drawX(120, -i)
    y = drawY(48, -i) + 10
    t.goto(x, y)
 t.goto(-120, 0)
 for i in range(180, 360):
    x = drawX(120, i)
    y = drawY(48, i)
    t.goto(x, y)
    t.fillcolor("#ffa79d")
    t.end_fill()
# 8
t.pu()
 t.goto(120, 70)
 t.pd()
 t.begin_fill()
 t.pensize(4)
 t.pencolor("#fff0f3")
 for i in range(1800):
    x = drawX(120, 0.1 * i)
    y = drawY(-18, i) + 10
    t.goto(x, y)
 t.goto(-120, 70)
 t.pensize(1)
 for i in range(180, 360):
    x = drawX(120, i)
    y = drawY(48, i) + 70
    t.goto(x, y)
    t.fillcolor("#fff0f3")
    t.end_fill()
# 9
t.pu()
 t.goto(80, 70)
 t.pd()
 t.begin_fill()
 t.pencolor("#6f3732")
 t.goto(80, 120)
 for i in range(180):
    x = drawX(80, i)
    y = drawY(32, i) + 120
    t.goto(x, y)
 t.goto(-80, 70)
 for i in range(180, 360):
    x = drawX(80, i)
    y = drawY(32, i) + 70
    t.goto(x, y)
    t.fillcolor("#6f3732")
    t.end_fill()
# 10
t.pu()
 t.goto(80, 120)
 t.pd()
 t.pencolor("#ffaaa0")
 t.begin_fill()
 for i in range(360):
    x = drawX(80, i)
    y = drawY(32, i) + 120
    t.goto(x, y)
    t.fillcolor("#ffaaa0")
    t.end_fill()
# 11
t.pu()
 t.goto(70, 120)
 t.pd()
 t.pencolor("#ffc3be")
 t.begin_fill()
 for i in range(360):
    x = drawX(70, i)
    y = drawY(28, i) + 120
    t.goto(x, y)
    t.fillcolor("#ffc3be")
    t.end_fill()
# 12
t.pu()
 t.goto(80, 120)
 t.pd()
 t.begin_fill()
 t.pensize(3)
 t.pencolor("#ffaaa0")
 for i in range(1800):
    x = drawX(80, 0.1 * i)
    y = drawY(-12, i) + 80
    t.goto(x, y)
 t.goto(-80, 120)
 t.pensize(1)
 for i in range(180, 360):
    x = drawX(80, i)
    y = drawY(32, i) + 120
    t.goto(x, y)
    t.fillcolor("#ffaaa0")
    t.end_fill()
# 13
t.pu()
 t.goto(64, 120)
 t.pd()
 t.pencolor("#b1c9e9")
 t.begin_fill()
 for i in range(360):
    x = drawX(4, i) + 60
    y = drawY(1, i) + 120
    t.goto(x, y)
 t.goto(64, 170)
 for i in range(540):
    x = drawX(4, i) + 60
    y = drawY(1, i) + 170
    t.goto(x, y)
    t.goto(56, 120)
    t.fillcolor("#b1c9e9")
    t.end_fill()
 t.pencolor("white")
 t.pensize(2)
 for i in range(1, 6):
    t.goto(64, 120 + 10 * i)
    t.pu()
    t.goto(56, 120 + 10 * i)
    t.pd()
# 14
color = ["#e28cb9", "#805a8c", "#eaa989", "#6e90b7", "#b8b68f", "#e174b5", "#cf737c", "#7c8782"]
for i in range(80):
    t.pu()
    x = r.randint(-120, 120)
    y = r.randint(-25, 30)
    t.goto(x, y)
    t.pd()
    t.dot(r.randint(2, 5), color[r.randint(0, 7)])
for i in range(40):
    t.pu()
    x = r.randint(-90, 90)
    y = r.randint(-35, 10)
    t.goto(x, y)
    t.pd()
    t.dot(r.randint(2, 5), color[r.randint(0, 7)])
for i in range(40):
    t.pu()
    x = r.randint(-80, 80)
    y = r.randint(60, 90)
    t.goto(x, y)
    t.pd()
    t.dot(r.randint(2, 5), color[r.randint(0, 7)])
for i in range(30):
    t.pu()
    x = r.randint(-50, 50)
    y = r.randint(45, 70)
    t.goto(x, y)
    t.pd()
    t.dot(r.randint(2, 5), color[r.randint(0, 7)])
# Random dots
for i in range(50):
    t.pu()
    x = r.randint(-500, 500)
    y = r.randint(120, 300)
    t.goto(x, y)
    t.pd()
    t.dot(r.randint(3, 5), color[r.randint(0, 7)])
 t.seth(90)
 t.pu()
 t.goto(0, 0)
 t.fd(210)
 t.left(90)
 t.fd(170)
 t.pd()
 t.write("Happy Birthday", font=("Curlz MT", 50))
 t.done()</code>

The resulting image (shown in the attached screenshot) demonstrates the cake drawing, and the author reflects that the code is repetitive and could be refactored, encouraging readers to apply parametric equations and improve coding practices.

graphicsturtledrawingcakeparametric
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.