Editor

Diwali Diya in Python Turtle

Advanced · Festivals · 78 lines · draws in about 11 seconds

This program draws a glowing clay diya for Diwali, with an oval bowl worked out using sine and cosine and a flame made of three teardrops.

Diwali Diya in Python Turtle: the finished drawing
import math
import turtle
screen = turtle.Screen()
screen.title("Diwali Diya")
screen.bgcolor("#1b0d2a")
t = turtle.Turtle()
t.speed(5)
def oval(x, y, width, height, color, start=0, end=360):
"""Fill an oval centred at (x, y), or the part of it from angle start to angle end."""
points = []
for angle in range(start, end + 1, 5):
a = math.radians(angle)
points.append((x + width / 2 * math.cos(a), y + height / 2 * math.sin(a)))
t.penup()
t.goto(points[0])
t.pendown()
t.color(color)
t.begin_fill()
for point in points:
t.goto(point)
t.end_fill()
def flame(x, y, radius, height, color):
"""A teardrop: a round bottom centred at (x, y) and a point `height` above it."""
lean = math.degrees(math.asin(radius / height))
side = math.sqrt(height ** 2 - radius ** 2)
t.penup()
t.goto(x, y + height)
t.setheading(270 + lean)
t.pendown()
t.color(color)
t.begin_fill()
t.forward(side)
t.circle(-radius, 180 + 2 * lean)
t.forward(side)
t.end_fill()
# A warm glow: big dots, darkest on the outside
t.penup()
t.goto(0, 10)
for size, color in [(380, "#2a1236"), (300, "#3d1838"), (220, "#5a2234"), (150, "#7a2e2a")]:
t.dot(size, color)
# The clay lamp: a foot, a round bowl and the rim with oil inside
oval(0, -150, 110, 36, "#8a3212")
oval(0, -60, 280, 180, "#b5441b", 180, 360)
oval(0, -60, 280, 56, "#e07b39")
oval(0, -56, 236, 36, "#5c1d06")
# Gold dots painted round the bowl
t.penup()
for angle in range(205, 340, 15):
a = math.radians(angle)
t.goto(105 * math.cos(a), -70 + 60 * math.sin(a))
t.dot(12, "gold")
# The wick
t.goto(0, -58)
t.setheading(90)
t.pendown()
t.pensize(5)
t.color("#2b1a10")
t.forward(26)
t.pensize(1)
# Three flames inside each other: orange, gold, then pale yellow
flame(0, -4, 34, 120, "darkorange")
flame(0, -10, 23, 84, "gold")
flame(0, -16, 12, 46, "lightyellow")
t.hideturtle()
turtle.done()

How the code works

Ovals from points

Turtle has no oval command, so oval() works out points with math.cos() and math.sin(), stretching a circle to the width and height it is given. With start=180 and end=360 it draws only the bottom half, which becomes the bowl.

def oval(x, y, width, height, color, start=0, end=360):
    """Fill an oval centred at (x, y), or the part of it from angle start to angle end."""
    points = []
    for angle in range(start, end + 1, 5):
        a = math.radians(angle)
        points.append((x + width / 2 * math.cos(a), y + height / 2 * math.sin(a)))
    t.penup()
    t.goto(points[0])
    t.pendown()
    t.color(color)
    t.begin_fill()
    for point in points:
        t.goto(point)
    t.end_fill()

A teardrop flame

A flame is a straight side down to a round bottom, circle() round the bottom, and a straight side back up to the tip. math.asin() finds the angle at which the straight sides meet the round part smoothly.

def flame(x, y, radius, height, color):
    """A teardrop: a round bottom centred at (x, y) and a point `height` above it."""
    lean = math.degrees(math.asin(radius / height))
    side = math.sqrt(height ** 2 - radius ** 2)
    t.penup()
    t.goto(x, y + height)
    t.setheading(270 + lean)
    t.pendown()
    t.color(color)
    t.begin_fill()
    t.forward(side)
    t.circle(-radius, 180 + 2 * lean)
    t.forward(side)
    t.end_fill()

A glow from big dots

Four dots, drawn from the biggest and darkest to the smallest and warmest, look like light spreading out from the flame.

for size, color in [(380, "#2a1236"), (300, "#3d1838"), (220, "#5a2234"), (150, "#7a2e2a")]:
    t.dot(size, color)

Three flames, one inside another

Drawing a smaller, paler flame on top of a bigger one gives the flame a hot, bright centre.

flame(0, -4, 34, 120, "darkorange")
flame(0, -10, 23, 84, "gold")
flame(0, -16, 12, 46, "lightyellow")

Make it yours

Change the code above and press Run. Some ideas:

  • Add a fifth glow ring by putting (450, "#22102f") at the front of the glow list.
  • Change range(205, 340, 15) to range(205, 340, 30) for fewer gold dots, further apart.
  • Change "darkorange" to "orangered" for a redder flame.

What it uses

Every turtle command the site supports is listed on Python turtle online.