引言
在Python的生态系统中,Turtle模块为图形编程提供了简单直观的方式。本项目旨在利用Turtle模块创建一个有趣的交通灯模拟器,结合倒计时效果。我将分步解释这个项目。
先放上最终效果图:
这个源码也放我仓库了
GitHub hewei2723/LBE
首先对于三种交通灯有四种情况:
红(Red)黄(Yellow)绿(Green)无信号(B)
红灰灰 灰黄灰 灰灰绿
我用rbb byb bbg来代替,
我本来想直接一个点一个点的变换的,但是发现turtle不行,所以就给每个状态打包绘制,就跟遥控器的滚码一样
红灰灰 灰黄灰 灰灰绿 分别代表红灯 黄灯 绿灯三个状态。
红灯行 绿灯停,黄灯亮了等一等,交通灯切换是直接用覆盖来变化的。当红灯开始时会画三个圆圈
红 灰 灰
然后黄灯会直接覆盖在红灯上,效果如图:
函数 draw_traffic_light
这个是专门用来画三个灯的函数
def draw_traffic_light(x, y, radius, color, label):
t.penup()
t.goto(x, y - radius) # 移动到圆心位置
t.pendown()
t.speed(50)
# 画圆
t.color("black", color)
t.begin_fill()
t.circle(radius)
t.end_fill()
# 添加文字说明
t.penup()
t.goto(x, y - radius - 20) # 调整文字位置
t.pendown()
t.write(label, align="center", font=("Arial", 10, "normal"))
作用:
- 绘制一个交通灯的圆形灯和相关状态文字。
- 接受参数:位置(x, y)、半径、颜色、标签。
效果
思维:
- 使用Turtle模块的
circle
函数绘制圆形。 - 考虑文字的位置,使用
write
函数添加文字说明。
函数 rbb
def rbb():
draw_traffic_light(50, 100, traffic_light_radius, "red", "红灯禁止通行")
draw_traffic_light(150, 100, traffic_light_radius, "gray", "")
draw_traffic_light(250, 100, traffic_light_radius, "gray", "")
countdown_timer(5)
byb()
bbg()
作用:
- 模拟红灯状态。
- 调用
draw_traffic_light
绘制红灯、灰色灯(不可见)、灰色灯。 - 调用
countdown_timer
进行倒计时。 - 调用其他两个状态函数。
思维:
- 状态的变迁和倒计时函数的嵌套调用。
- 灰色灯表示状态切换时的过渡。
函数 byb
def byb():
draw_traffic_light(50, 100, traffic_light_radius, "gray", "")
draw_traffic_light(150, 100, traffic_light_radius, "yellow", "黄灯请等待")
draw_traffic_light(250, 100, traffic_light_radius, "gray", "")
countdown_timer(3)
作用:
- 模拟黄灯状态。
- 调用
draw_traffic_light
绘制灰色灯、黄灯、灰色灯。 - 调用
countdown_timer
进行倒计时。
思维:
- 通过灰色灯表示状态切换时的过渡。
函数 bbg
def bbg():
draw_traffic_light(50, 100, traffic_light_radius, "gray", "")
draw_traffic_light(150, 100, traffic_light_radius, "gray", "")
draw_traffic_light(250, 100, traffic_light_radius, "green", "绿灯可以通行")
countdown_timer(5)
byb()
rbb()
作用:
- 模拟绿灯状态。
- 调用
draw_traffic_light
绘制灰色灯、灰色灯、绿灯。 - 调用
countdown_timer
进行倒计时。 - 调用其他两个状态函数。
思维:
- 通过灰色灯表示状态切换时的过渡。
- 状态的循环切换。
函数 drawGap
和 drawLine
def drawGap():
turtle.penup()
turtle.fd(5)
def drawLine(draw):
drawGap()
turtle.pendown() if draw else turtle.penup()
turtle.fd(40)
drawGap()
turtle.right(90)
作用:
- 用于绘制数字显示的空隙和线段。
drawGap
绘制空隙,drawLine
绘制线段。
思维:
- 控制Turtle画笔的抬起和放下,形成数字的显示效果。
效果
函数 drawDigits
和 drawDate
def drawDigits(digit):
# ...(略)
def drawDate(date, start_position=(330, 100)):
# ...(略)
作用:
drawDigits
用于绘制数字的各个线段。drawDate
用于绘制倒计时数字。
思维:
- 利用
drawLine
函数,根据数字的每一位,绘制相应的线段。
函数 countdown_timer
def countdown_timer(time, start_position=(330, 100)):
turtle.pensize(5)
turtle.speed(50)
drawDate(time, start_position)
作用:
- 用于触发倒计时显示。
思维:
- 控制Turtle的画笔粗细和速度,调用
drawDate
进行倒计时数字的显示。
主循环
# 主循环
t = turtle.Turtle()
t.hideturtle()
width = 500
height = 200
turtle.setup(width, height)
turtle.setworldcoordinates(0, 0, width, height)
num_lines = 4
line_spacing = width / (num_lines + 1)
t.speed(100)
for i in range(1, num_lines + 1):
x = i * line_spacing
t.penup()
t.goto(x, 0)
t.pendown()
t.left(90)
t.forward(height)
t.right(90)
traffic_light_radius = 30
rbb()
turtle.mainloop()
作用:
- 设置Turtle画布和坐标系。
- 绘制交叉口的道路线。
- 调用最初的交通灯状态函数。
思维:
-
利用循环绘制道路线。
-
通过Turtle模块的坐标系设置,确定交叉口的位置。
完整代码
import turtle
import time
def draw_traffic_light(x, y, radius, color, label):
t.penup()
t.goto(x, y - radius) # 移动到圆心位置
t.pendown()
t.speed(50)
# 画圆
t.color("black", color)
t.begin_fill()
t.circle(radius)
t.end_fill()
# 添加文字说明
t.penup()
t.goto(x, y - radius - 20) # 调整文字位置
t.pendown()
t.write(label, align="center", font=("Arial", 10, "normal"))
# 定义rbb函数,用于绘制交通灯
def rbb():
# 绘制红色交通灯,位置为(50, 100),半径为traffic_light_radius,状态为"红灯禁止通行"
draw_traffic_light(50, 100, traffic_light_radius, "red", "红灯禁止通行")
# 绘制灰色交通灯,位置为(150, 100),半径为traffic_light_radius,状态为""
draw_traffic_light(150, 100, traffic_light_radius, "gray", "")
# 绘制灰色交通灯,位置为(250, 100),半径为traffic_light_radius,状态为""
draw_traffic_light(250, 100, traffic_light_radius, "gray", "")
# 调用countdown_timer函数,等待5秒
countdown_timer(5)
# 调用byb函数
byb()
# 调用bbg函数
bbg()
# 定义byb函数,用于绘制交通灯
def byb():
# 绘制灰色交通灯,位置为(50, 100),半径为traffic_light_radius,状态为""
draw_traffic_light(50, 100, traffic_light_radius, "gray", "")
# 绘制黄色交通灯,位置为(150, 100),半径为traffic_light_radius,状态为"黄灯请等待"
draw_traffic_light(150, 100, traffic_light_radius, "yellow", "黄灯请等待")
# 绘制灰色交通灯,位置为(250, 100),半径为traffic_light_radius,状态为""
draw_traffic_light(250, 100, traffic_light_radius, "gray", "")
# 调用countdown_timer函数,等待3秒
countdown_timer(3)
# 定义bbg函数,用于绘制交通灯
def bbg():
# 绘制灰色交通灯,位置为(50, 100),半径为traffic_light_radius,状态为""
draw_traffic_light(50, 100, traffic_light_radius, "gray", "")
# 绘制灰色交通灯,位置为(150, 100),半径为traffic_light_radius,状态为""
draw_traffic_light(150, 100, traffic_light_radius, "gray", "")
# 绘制绿色交通灯,位置为(250, 100),半径为traffic_light_radius,状态为"绿灯可以通行"
draw_traffic_light(250, 100, traffic_light_radius, "green", "绿灯可以通行")
# 调用countdown_timer函数,等待5秒
countdown_timer(5)
# 调用byb函数
byb()
# 调用rbb函数
rbb()
def drawGap():
turtle.penup()
turtle.fd(5)
def drawLine(draw):
drawGap()
turtle.pendown() if draw else turtle.penup()
turtle.fd(40)
drawGap()
turtle.right(90)
def drawDigits(digit):
drawLine(True) if digit in [2, 3, 4, 5, 6, 8, 9] else drawLine(False)
drawLine(True) if digit in [0, 1, 3, 4, 5, 6, 7, 8, 9] else drawLine(False)
drawLine(True) if digit in [0, 2, 3, 5, 6, 8, 9] else drawLine(False)
drawLine(True) if digit in [0, 2, 6, 8] else drawLine(False)
turtle.left(90)
drawLine(True) if digit in [0, 4, 5, 6, 8, 9] else drawLine(False)
drawLine(True) if digit in [0, 2, 3, 5, 6, 7, 8, 9] else drawLine(False)
drawLine(True) if digit in [0, 1, 2, 3, 4, 7, 8, 9] else drawLine(False)
turtle.left(180)
turtle.penup()
turtle.fd(15)
# 定义一个函数,用于绘制日期,参数date为日期,start_position为日期位置,默认为(330, 100)
def drawDate(date, start_position=(330, 100)):
# 抬起画笔
turtle.penup()
# 移动画笔到指定位置
turtle.goto(start_position)
# 设置画笔颜色
turtle.pencolor("red")
# 从日期开始,从后往前遍历,直到0
for i in reversed(range(date + 1)):
# 将日期转换为字符串
num = str(i)
# 遍历字符串中的每一个数字
for n in num:
# 调用drawDigits函数绘制数字
drawDigits(eval(n))
# 抬起画笔
turtle.penup()
# 向后移动40像素
turtle.forward(40)
# 清除画布
turtle.clear()
# 抬起画笔
turtle.penup()
# 移动画笔到指定位置
turtle.goto(start_position)
# 定义一个函数countdown_timer,参数time和start_position,time为时间,start_position为坐标
def countdown_timer(time, start_position=(330, 100)):
# 设置画笔宽度
turtle.pensize(5)
# 设置画笔速度
turtle.speed(50)
# 调用drawDate函数,参数time和start_position
drawDate(time, start_position)
# 创建一个Turtle对象
t = turtle.Turtle()
# 隐藏Turtle对象
t.hideturtle()
# 设置画布宽度
width = 500
# 设置画布高度
height = 200
# 设置画布大小
turtle.setup(width, height)
# 设置画布坐标系
turtle.setworldcoordinates(0, 0, width, height)
# 设置画布行数
num_lines = 4
# 计算每行之间的间距
line_spacing = width / (num_lines + 1)
# 设置画笔速度
t.speed(2)
# 循环画线
for i in range(1, num_lines + 1):
# 计算每行x坐标
x = i * line_spacing
# 画笔抬起
t.penup()
# 移动画笔到x坐标
t.goto(x, 0)
# 画笔落下
t.pendown()
# 画笔左转90度
t.left(90)
# 画笔向前移动画布高度
t.forward(height)
# 画笔右转90度
t.right(90)
traffic_light_radius = 30
rbb()
turtle.mainloop()