综合项目

运用所学知识

现在我们已经学习了海龟绘图的各种技巧,让我们通过一些综合项目来练习所学知识!

项目一:海底世界

让我们创建一个美丽的海底世界:

import turtle

# 设置背景
turtle.bgcolor("darkblue")
screen = turtle.Screen()

# 创建海龟
t = turtle.Turtle()
t.speed(5)

# 画海底
t.penup()
t.goto(-300, -200)
t.pendown()
t.fillcolor("brown")
t.pencolor("brown")
t.begin_fill()
t.goto(300, -200)
t.goto(300, -100)
t.goto(-300, -100)
t.goto(-300, -200)
t.end_fill()

# 画海草
def draw_seaweed(x, y, height):
    t.penup()
    t.goto(x, y)
    t.pendown()
    t.fillcolor("green")
    t.pencolor("green")
    t.begin_fill()
    t.setheading(90)
    t.forward(height)
    t.right(45)
    t.forward(20)
    t.right(90)
    t.forward(20)
    t.right(45)
    t.forward(height)
    t.end_fill()

# 画多根海草
draw_seaweed(-200, -100, 80)
draw_seaweed(-100, -100, 120)
draw_seaweed(0, -100, 100)
draw_seaweed(100, -100, 90)
draw_seaweed(200, -100, 110)

# 画鱼(彻底修正眼睛位置:严格贴合鱼身圆形)
def draw_fish(x, y, size, color):
    # x,y 是鱼身体(圆形)的中心坐标,size是鱼身半径
    t.penup()
    t.goto(x, y)
    t.pendown()

    # 1. 画鱼身体(圆形,鱼身朝右,尾巴在左)
    t.fillcolor(color)
    t.pencolor(color)
    t.begin_fill()
    t.circle(size)  # 以(x,y)为中心画圆形身体
    t.end_fill()

    # 2. 画鱼尾(精准衔接鱼身左侧,分叉形鱼尾)
    t.penup()
    t.goto(x - size, y + size * 0.2)  # 鱼尾根部上沿
    t.pendown()
    t.begin_fill()
    t.setheading(150)  # 朝左上方
    t.forward(size * 1.5)  # 左上鱼尾边
    t.goto(x - size, y)    # 回到鱼尾根部中点
    t.setheading(210)      # 朝左下方
    t.forward(size * 1.5)  # 左下鱼尾边
    t.goto(x - size, y - size * 0.2)  # 鱼尾根部下沿
    t.setheading(150)      # 回朝上左
    t.forward(size * 1.5)  # 闭合鱼尾
    t.end_fill()

    # 3. 画鱼嘴(小弧线,鱼头部右侧)
    t.penup()
    t.goto(x + size, y)  # 鱼头部最右侧
    t.pendown()
    t.pencolor("black")
    t.setheading(20)     # 朝上偏右
    t.circle(size * 0.3, 40)  # 小弧线鱼嘴
    t.pencolor(color)    # 恢复鱼身颜色

    # 4. 画眼睛(核心修正:严格落在鱼身右上方,不超出边界)
    # 眼睛中心坐标:鱼身中心(x,y) 向右偏移 size*0.5,向上偏移 size*0.4
    # 这个比例确保眼睛完全在鱼身圆形内,且位置自然
    eye_x = x + size * 0.5
    eye_y = y + size * 0.4

    # 画眼白(大小随鱼身自适应,完全在鱼身上)
    t.penup()
    t.goto(eye_x, eye_y)
    t.pendown()
    t.fillcolor("white")
    t.begin_fill()
    t.circle(size / 10)  # 眼白半径=鱼身半径的1/10,不会超出
    t.end_fill()

    # 画眼珠(在眼白中心,更聚焦)
    t.penup()
    t.goto(eye_x + size/20, eye_y + size/20)
    t.pendown()
    t.fillcolor("black")
    t.begin_fill()
    t.circle(size / 20)  # 眼珠半径=鱼身半径的1/20
    t.end_fill()

# 画多条鱼(测试不同尺寸,眼睛都能精准落在鱼身上)
draw_fish(-150, 50, 30, "orange")
draw_fish(50, 80, 25, "yellow")
draw_fish(100, 20, 35, "red")

# 画气泡
def draw_bubble(x, y, size):
    t.penup()
    t.goto(x, y)
    t.pendown()
    t.fillcolor("white")
    t.pencolor("white")
    t.begin_fill()
    t.circle(size)
    t.end_fill()

# 画多个气泡
draw_bubble(-100, 150, 10)
draw_bubble(-80, 180, 5)
draw_bubble(150, 120, 8)
draw_bubble(170, 150, 12)

# 写标题
t.penup()
t.goto(0, 250)
t.pendown()
t.pencolor("white")
t.write("海底世界", font=("Arial", 24, "bold"), align="center")

# 隐藏海龟
t.hideturtle()

# 保持窗口显示
turtle.done()

项目二:四季树

让我们画一棵展示四季变化的树:

import turtle

# 创建屏幕和海龟
screen = turtle.Screen()
t = turtle.Turtle()
t.speed(5)

# 定义当前季节,用于循环切换
current_season = 0  # 0:春天, 1:夏天, 2:秋天, 3:冬天

# 画树干
def draw_trunk():
    t.penup()
    t.goto(0, -100)
    t.pendown()
    t.fillcolor("brown")
    t.pencolor("brown")
    t.begin_fill()
    t.setheading(90)
    t.forward(100)
    t.right(90)
    t.forward(20)
    t.right(90)
    t.forward(100)
    t.end_fill()

# 画树叶
def draw_leaves(color):
    t.penup()
    t.goto(-50, 0)
    t.pendown()
    t.fillcolor(color)
    t.pencolor(color)
    t.begin_fill()
    t.circle(60)
    t.end_fill()

# 春天树
def draw_spring():
    t.reset()
    t.speed(5)  # 重置后恢复速度
    screen.bgcolor("lightblue")
    draw_trunk()
    draw_leaves("lightgreen")
    t.penup()
    t.goto(0, 150)
    t.pendown()
    t.write("春天", font=("Arial", 20, "bold"), align="center")

# 夏天树
def draw_summer():
    t.reset()
    t.speed(5)
    screen.bgcolor("skyblue")
    draw_trunk()
    draw_leaves("green")
    t.penup()
    t.goto(0, 150)
    t.pendown()
    t.write("夏天", font=("Arial", 20, "bold"), align="center")

# 秋天树
def draw_autumn():
    t.reset()
    t.speed(5)
    screen.bgcolor("lightyellow")
    draw_trunk()
    draw_leaves("orange")
    t.penup()
    t.goto(0, 150)
    t.pendown()
    t.write("秋天", font=("Arial", 20, "bold"), align="center")

# 冬天树
def draw_winter():
    t.reset()
    t.speed(5)
    screen.bgcolor("lightgray")
    draw_trunk()
    # 冬天没有树叶
    t.penup()
    t.goto(0, 150)
    t.pendown()
    t.write("冬天", font=("Arial", 20, "bold"), align="center")

    # 画雪
    for i in range(50):
        if current_season == 3:
            x = -200 + i * 8
            y = 50 + (i % 5) * 20
            t.penup()
            t.goto(x, y)
            t.pendown()
            t.fillcolor("white")
            t.begin_fill()
            t.circle(3)
            t.end_fill()

# 点击屏幕切换季节的核心函数
def switch_season(x, y):
    global current_season
    # 根据当前季节切换到下一个
    current_season = (current_season + 1) % 4
    if current_season == 0:
        draw_spring()
    elif current_season == 1:
        draw_summer()
    elif current_season == 2:
        draw_autumn()
    elif current_season == 3:
        draw_winter()

# 初始化显示春天
draw_spring()

# 设置点击事件:点击屏幕任意位置触发季节切换
screen.onscreenclick(switch_season)

# 保持窗口显示
turtle.done()

项目三:太空冒险

让我们创建一个太空冒险场景:

import turtle
import random

# 设置背景
turtle.bgcolor("black")
screen = turtle.Screen()

# 创建海龟
t = turtle.Turtle()
t.speed(0)  # 最快速度

# 画星星
def draw_star(x, y, size, color):
    t.penup()
    t.goto(x, y)
    t.pendown()
    t.fillcolor(color)
    t.pencolor(color)
    t.begin_fill()

    # 画五角星
    for i in range(5):
        t.forward(size)
        t.right(144)

    t.end_fill()

# 画多个星星
for i in range(30):
    x = random.randint(-300, 300)
    y = random.randint(50, 300)
    size = random.randint(5, 20)
    color = random.choice(["white", "yellow", "lightblue"])
    draw_star(x, y, size, color)

# 画地球
t.penup()
t.goto(0, -50)
t.pendown()
t.fillcolor("blue")
t.pencolor("blue")
t.begin_fill()
t.circle(50)
t.end_fill()

# 画地球上的陆地
t.penup()
t.goto(-30, -30)
t.pendown()
t.fillcolor("green")
t.pencolor("green")
t.begin_fill()
t.circle(20)
t.end_fill()

# 画火箭(彻底修正顶部:用坐标定位绘制三角形顶部)
def draw_rocket(x, y):
    # x,y 是火箭底部左侧的起点坐标
    t.penup()
    t.goto(x, y)
    t.pendown()

    # 1. 绘制火箭主体(红色矩形)
    t.fillcolor("red")
    t.pencolor("red")
    t.begin_fill()
    # 从(x,y)开始,按顺时针画矩形
    t.setheading(90)   # 朝上
    t.forward(60)      # 向上到(x, y+60) → 顶部左侧
    t.right(90)        # 朝右
    t.forward(20)      # 向右到(x+20, y+60) → 顶部右侧
    t.right(90)        # 朝下
    t.forward(60)      # 向下到(x+20, y) → 底部右侧
    t.right(90)        # 朝左
    t.forward(20)      # 向左回到(x,y) → 底部左侧
    t.end_fill()

    # 2. 绘制火箭顶部(白色三角形,精准覆盖主体顶端)
    t.fillcolor("white")
    t.pencolor("white")
    t.begin_fill()
    # 手动定位三角形的三个顶点,确保和主体匹配
    t.penup()
    t.goto(x, y+60)          # 第一个点:火箭主体顶部左侧
    t.pendown()
    t.goto(x+10, y+75)       # 第二个点:火箭顶部顶点(中间向上延伸)
    t.goto(x+20, y+60)       # 第三个点:火箭主体顶部右侧
    t.goto(x, y+60)          # 回到第一个点,闭合三角形
    t.end_fill()

    # 3. 绘制火箭窗口
    t.penup()
    t.goto(x + 10, y + 30)   # 窗口在火箭中心位置
    t.pendown()
    t.fillcolor("lightblue")
    t.pencolor("lightblue")
    t.begin_fill()
    t.circle(8)
    t.end_fill()

# 画火箭
draw_rocket(-150, -100)

# 画卫星(太阳能板以中心对称)
def draw_satellite(x, y):
    t.penup()
    t.goto(x, y)
    t.pendown()

    # 卫星主体(圆形)
    t.fillcolor("gray")
    t.pencolor("gray")
    t.begin_fill()
    t.circle(15)
    t.end_fill()

    # 太阳能板(以卫星中心为对称轴)
    # 左侧板
    t.penup()
    t.goto(x, y)
    t.setheading(180)
    t.forward(15)
    t.pendown()
    t.forward(40)
    # 右侧板
    t.penup()
    t.goto(x, y)
    t.setheading(0)
    t.forward(15)
    t.pendown()
    t.forward(40)
    # 上侧板
    t.penup()
    t.goto(x, y)
    t.setheading(90)
    t.forward(15)
    t.pendown()
    t.forward(30)
    # 下侧板
    t.penup()
    t.goto(x, y)
    t.setheading(270)
    t.forward(15)
    t.pendown()
    t.forward(30)

# 画卫星
draw_satellite(150, 50)

# 写标题
t.penup()
t.goto(0, 200)
t.pendown()
t.pencolor("white")
t.write("太空冒险", font=("Arial", 24, "bold"), align="center")

# 隐藏海龟
t.hideturtle()

# 保持窗口显示
turtle.done()

项目四:互动游戏

让我们创建一个简单的互动游戏:海龟接球游戏

import turtle
import random  # 用于生成随机角度

# 设置屏幕
screen = turtle.Screen()
screen.bgcolor("lightblue")
screen.title("海龟接球游戏")
screen.tracer(0)  # 关闭自动刷新,提升动画流畅度

# 创建玩家海龟
player = turtle.Turtle()
player.shape("turtle")
player.color("green")
player.penup()
player.goto(0, -200)

# 创建球
ball = turtle.Turtle()
ball.shape("circle")
ball.color("red")
ball.penup()
ball.goto(0, 200)

# 分数
score = 0
score_turtle = turtle.Turtle()
score_turtle.hideturtle()
score_turtle.penup()
score_turtle.goto(-200, 250)
score_turtle.write("分数: 0", font=("Arial", 16, "normal"))

# 游戏状态标志
game_over = False
ball_returning = False  # 标记球是否正在返回上方
return_angle = 0        # 球返回时的水平偏移角度

# 游戏结束提示海龟
game_over_turtle = turtle.Turtle()
game_over_turtle.hideturtle()
game_over_turtle.penup()
game_over_turtle.goto(0, 0)

# 重新开始提示海龟
restart_turtle = turtle.Turtle()
restart_turtle.hideturtle()
restart_turtle.penup()
restart_turtle.goto(0, -50)

# 游戏说明
instructions = turtle.Turtle()
instructions.hideturtle()
instructions.penup()
instructions.goto(0, -250)
instructions.write("使用左右方向键移动海龟接球", font=("Arial", 12, "normal"), align="center")

# 移动玩家
def move_left():
    if not game_over:  # 游戏未结束时才能移动
        x = player.xcor()
        if x > -280:  # 限制左边界,防止移出屏幕
            player.setx(x - 20)

def move_right():
    if not game_over:  # 游戏未结束时才能移动
        x = player.xcor()
        if x < 280:  # 限制右边界,防止移出屏幕
            player.setx(x + 20)

# 重置游戏(重新开始)
def reset_game():
    global score, game_over, ball_returning
    # 重置游戏状态
    game_over = False
    ball_returning = False
    score = 0

    # 清空游戏结束提示
    game_over_turtle.clear()
    restart_turtle.clear()

    # 显示玩家和球
    player.showturtle()
    ball.showturtle()

    # 重置位置
    player.goto(0, -200)
    ball.goto(0, 200)

    # 重置分数显示
    score_turtle.clear()
    score_turtle.write("分数: 0", font=("Arial", 16, "normal"))

# 球返回上方的逻辑(带角度缓慢移动)
def move_ball_up():
    global ball_returning, return_angle
    # 球的当前位置
    x, y = ball.pos()

    # 还没到目标高度,继续移动
    if y < 195:  # 目标高度(略低于200,避免重复触发)
        # 按角度向上+水平移动
        ball.setx(x + return_angle)
        ball.sety(y + 5)  # 上升速度
    else:
        # 到达目标高度,停止返回
        ball_returning = False

# 游戏循环
def game_loop():
    global score, game_over, ball_returning, return_angle

    if not game_over:
        # 如果球正在返回上方,执行返回逻辑
        if ball_returning:
            move_ball_up()
        else:
            # 球正常下落
            y = ball.ycor()
            ball.sety(y - 5)

            # 检查是否接到球
            if ball.distance(player) < 30:
                score += 1
                score_turtle.clear()
                score_turtle.write(f"分数: {score}", font=("Arial", 16, "normal"))
                # 触发球返回逻辑:生成随机角度(-3到3之间,控制水平偏移)
                ball_returning = True
                return_angle = random.uniform(-3, 3)  # 随机左右偏移角度

        # 检查球是否落地(游戏结束条件)
        if ball.ycor() < -220:
            game_over = True
            # 隐藏玩家和球
            player.hideturtle()
            ball.hideturtle()
            # 显示游戏结束提示
            game_over_turtle.write("Game Over", font=("Arial", 30, "bold"), align="center")
            # 显示重新开始提示
            restart_turtle.write("按空格键重新开始", font=("Arial", 16, "normal"), align="center")

    screen.update()  # 手动刷新屏幕
    # 继续游戏循环(50ms执行一次)
    screen.ontimer(game_loop, 50)

# 键盘控制
screen.listen()
screen.onkey(move_left, "Left")
screen.onkey(move_right, "Right")
screen.onkey(reset_game, "space")  # 按空格键重新开始

# 开始游戏
reset_game()  # 初始化游戏
game_loop()

# 保持窗口显示
turtle.done()

练习

  1. 创建你自己的海底世界,添加更多海洋生物
  2. 创建一个城市场景,有建筑物、汽车和树木
  3. 创建一个简单的迷宫游戏
  4. 创建你自己的互动项目

小提示

  • 使用函数来组织代码,使它更易读
  • 使用注释来解释复杂部分
  • 尝试添加用户交互,如键盘控制或鼠标点击
  • 使用颜色和形状使你的项目更加生动

思考题

如果你想创建一个多关卡的游戏,应该如何组织代码呢?


恭喜你完成了所有教程!继续探索和创造更多有趣的海龟图形吧!🐢

Python 工具/在线模拟器/Python海龟绘图可视化
Python海龟绘图可视化 - https://www.cnbbx.com/python-editor/