首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Python turtle 模块可以编写游戏,是真的吗?

Python turtle 模块可以编写游戏,是真的吗?

作者头像
一枚大果壳
发布于 2022-08-23 05:42:25
发布于 2022-08-23 05:42:25
1.6K00
代码可运行
举报
文章被收录于专栏:编程驿站编程驿站
运行总次数:0
代码可运行

1. 前言

turtle(小海龟) 是 Python 内置的一个绘图模块,其实它不仅可以用来绘图,还可以制作简单的小游戏,甚至可以当成简易的 GUI 模块,编写简单的 GUI 程序。

本文使用 turtle 模块编写一个简单的小游戏,通过此程序的编写过程聊一聊对 turtle 模块的感悟。

编写游戏,如果要做专业的、趣味性高的,还是请找 **pygame**,本文用 turtle 编写游戏的目的是为了深度理解 turtle 的功能。

turtle 模块的使用相对而言较简单,对于基础方法不做讲解。只聊 turtle 模块中稍难或大家忽视的地方。

2. 需求描述

程序运行时,画布上会出现**一个红色的小球很多绿色、蓝色的小球**。

刚开始红色的小球会朝某一个方向移动,使用者可以通过按下上、下、左、右方向键控制红色小球的运动方向。

绿色、蓝色小球以初始的默认方向在画布上移动。

当红色的小球碰到绿色小球时,红色小球球体会变大,当红色小球碰到蓝色小球时,红色球体会变小。

当红色小球球体缩小到某一个阈值时,游戏结束。

3. 制作流程

3.1 初始化变量

本程序需要使用到 turtlerandommath 模块,使用之前,先导入。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import turtle
import random
import math
'''
初始化游戏界面大小
'''
# 游戏区域的宽度
game_wid = 600  
# 游戏区域的高度
game_hei = 400  
# 砖块的大小,以及每一个小球初始大小
cell = 20
# 红球初始大小
red_size = cell
# 红色小球
red_ball = None
# 存储绿色小球的列表
green_balls = []
# 存储蓝色小球的列表
blue_balls = []
# 红色小球的方向 当前方向 0 向右,90 向上 180 向左 -90 向下
dir = 0

上述代码说明:

红色小球只有一个,由变量 red_ball 保存,红色小球在运动过程中可以改大小,red_size 保存其大小。

绿色和蓝色小球会有很多,这里使用 green_ballsblue_balls 2 个列表存储。

3.2 通用函数

随机位置计算函数: 为小球们随机生成刚开始出现的位置。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'''
随机位置计算函数
'''
def rand_pos():
    # 水平有 30 个单元格,垂直有 20 个单元格
    x = random.randint(-14, 14)
    y = random.randint(-9, 9)
    return x * cell, y * cell

绘制指定填充颜色的小正方形: 在游戏里有一个虚拟区域,四周使用很多小正方形围起来。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'''
绘制一个指定填充颜色的正方形
填充颜色可以不指定
'''
def draw_square(color):
    if color is not None:
        # 的颜色就填充
        turtle.fillcolor(color)
        turtle.begin_fill()
    for i in range(4):
        turtle.fd(cell)
        turtle.left(90)
    if color is not None:
        turtle.end_fill()

自定义画笔形状:

使用 turtle 制作游戏的底层思想:

当我们导入 turtle 模块时,意味着我们有了一只可以在画布上画画的画笔,画笔的默认形状是一只小海龟。

本文称这支默认画笔叫主画笔,可以使用 turtle 模块中的 turtle.Turtle() 类创建更多画笔 ,并且可以使用 ``turtle模块提供的turtle.register_shape(name, shape)` 方法为每一支画笔定制画笔形状。

如上所述,是使用 turtle 设计游戏的关键。

强调一下:

通过主画笔创建更多的画笔,以及为每一个画笔设置不同的形状。是编写游戏的关键,游戏中的每一个角色,其本质是一支画笔,我们只是在控制画笔在画布上按我们设计好的轨迹移动。

本游戏中红、绿、蓝 3 种颜色的小球就是形状为圆形的画笔。

画笔清单: 红色小球画笔一支。 绿色小球画笔 n 支。 蓝色小球画笔 n 支。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'''
自定义画笔形状
name:画笔名称
color:可选项
'''
def custom_shape(name, size):
    turtle.begin_poly()
    turtle.penup()
    turtle.circle(size)
    turtle.end_poly()
    cs = turtle.get_poly()
    turtle.register_shape(name, cs)

turtle.register_shape(name, shape) 方法参数说明:

  • name: 自定义形状的名称。
  • shape: 由开发者绘制的形状。 开发者绘制的哪一部分图形用来充当画笔形状?turtle.begin_poly() 记录的第一点到由 turtle.end_poly() 记录的最后一点之间的图形作为画笔形状。 cs = turtle.get_poly() 可以理解为获取到刚绘制的图形,然后使用 turtle.register_shape(name, cs) 注册画笔形状,以后就可以随时使用此形状。 如上代码记录了一个圆的绘制过程,也就是创建了一个圆形的画笔形状。

移动到某个位置函数:

此函数用来让某一支画笔移到指定位置,不留下移动过程中的轨迹。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'''
移到某点
'''
def move_pos(pen, pos):
    pen.penup()
    pen.goto(pos)
    pen.pendown()

参数说明:

  • pen : 画笔对象。
  • pos:要移到的目标地。

注册键盘事件函数:

使用者可以通过键盘上的方向键更改红色小球的方向。

turtle 模块提供有很多事件,可以以交互式的方式使用turtleturtle 模块中主要有 2 类事件:键盘事件、点击事件。因 turtle 的工作重点还是绘制静态图案上,其动画绘制比较弱,所以它的事件少而简单。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'''
改变红色小球 4 方向的函数,
这些函数只有当使用者触发按键后方可调用,故这些函数也称为回调函数。
'''
def dir_right():
    global dir
    dir = 0
def dir_left():
    global dir
    dir = 180
def dir_up():
    global dir
    dir = 90
def dir_down():
    global dir
    dir = -90
   
'''
注册键盘响应事件,用来改变红球的方向
'''
def register_event():
    for key, f in {"Up": dir_up, "Down": dir_down, "Left": dir_left, "Right": dir_right}.items():
        turtle.onkey(f, key)
    turtle.listen()
'''
当红色小球遇到墙体后,也要修改方向
'''    
def is_meet_qt():
    global dir
    if red_ball.xcor() < -220:
        dir = 0
    if red_ball.xcor() > 240:
        dir = 180
    if red_ball.ycor() > 140:
        dir = -90
    if red_ball.ycor() < -120:
        dir = 90

红色的小球在 2 个时间点需要改变方向,一是使用者按下了方向键,一是碰到了墙体。

3.3 游戏角色函数

绘制墙体函数:

墙体是游戏中的虚拟区域,用来限制小球的活动范围。

Tips: 墙体由主画笔绘制。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'''
绘制四面的墙体
'''
def draw_blocks():
    # 隐藏画笔
    turtle.hideturtle()
    # 上下各30个单元格,左右各 20 个单元格
    for j in [30, 20, 30, 20]:
        for i in range(j):
            # 调用前面绘制正方形的函数
            draw_square('gray')
            turtle.fd(cell)
        turtle.right(90)
        turtle.fd(-cell)
    # 回到原点
    move_pos(turtle, (0, 0))

创建小球画笔: 此函数用来创建新画笔。本程序中的红色、蓝色、绿色小球都是由此函数创建的画笔,且外观形状是圆。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def init_ball(pos, color, shape):
    #  由主画笔创建新画笔
    ball = turtle.Turtle()
    ball.color(color)
    # 指定新画笔的形状,如果不指定,则为默认形状
    ball.shape(shape)
    # 移到随机位置
    move_pos(ball, pos)
    # 移动过程要不显示任何轨迹
    ball.penup()
    return ball

参数说明:

  • pos 创建画笔后画笔移动的位置。
  • color指定画笔和填充颜色。
  • shape 已经定义好的画笔形状名称。

创建绿色、蓝色小球:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def ran_gb_ball(balls, color):
    # 随机创建蓝色、绿色小球的频率,
    # 也就是说,不是调用此函数就一定会创建小球,概率大概是调用 5 次其中会有一次创建
    ran = random.randint(1, 5)
    # 随机一个角度
    a = random.randint(0, 360)
    # 1/5 的概率
    if ran == 5:
        turtle.tracer(False)
        # 每一个小球就是一只画笔
        ball = init_ball(rand_pos(), color, 'ball')
        ball.seth(a)
        # 添加到列表中
        balls.append(ball)
        turtle.tracer(True)

为什么要设置一个概率值?

适当控制蓝色、绿色小球的数量。

turtle.tracer(False) 方法的作用:是否显示画笔绘制过程动画。False 关闭动画效果,True 打开动画效果。

这里设置为 False 的原因是不希望用户看到新画笔创建过程。

蓝色、绿色小球的移动函数:

蓝色、绿色小球被创建后会移到一个随机位置,然后按默认方向移动。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def gb_ball_m(balls):
    s = 20
    a = random.randint(0, 360)
    r = random.randint(0, 10)
    for b in balls:
        b.fd(s)
        if b.xcor() < -220 or b.xcor() > 240 or b.ycor() > 140 or b.ycor() < -120:
            b.goto(rand_pos())

当小球碰到墙体后让其再随机移到墙体内部(简单粗粗暴!!)。

红色球是否碰到了蓝色或绿色小球:

此函数逻辑不复杂,计算小球相互之间的坐标,判断坐标是否重叠。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'''
红球是否碰到绿、蓝球
'''
def r_g_b_meet():
    global red_size
    # 红色小球的坐标
    s_x, s_y = red_ball.pos()
    # 迭代绿色小球,蓝色小球列表
    for bs in [green_balls, blue_balls]:
        for b in bs:
            # 计算蓝色或绿色小球坐标
            f_x, f_y = b.pos()
            # 计算和红色球之间的距离
            x_ = math.fabs(s_x - f_x)
            y_ = math.fabs(s_y - f_y)
            # 碰撞距离:两个球的半径之和
            h = cell + red_size
            if 0 <= x_ <= h and y_ >= 0 and y_ <= h:
                if b in green_balls:
                    # 遇到绿色球红球变大
                    red_size += 2
                if b in blue_balls:
                    # 遇到蓝色球红球变大
                    red_size -= 2
                # 关键代码    
                custom_shape('red', red_size)
                return True
    return False

上述代码整体逻辑不复杂。而 custom_shape('red', red_size) 是关键代码,因红色小球的半径发生了变化,所以需要重新定制红色小球的外观形状,这样才能在画布上看到半径变化的红色小球。

3.4 让小球动起来

怎样让小球动起来?

每隔一定时间,让小球重新移动。 turtle.ontimer(ball_move, 100) 是让小球动起来的核心逻辑,每隔一定时间,重新移动红、蓝、绿外观如圆形状的小球。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def ball_move():
    red_ball.seth(dir)
    red_ball.fd(40)
    # 检查红球是否碰到墙体
    is_meet_qt()
    # 随机创建绿色小球
    ran_gb_ball(green_balls, 'green')
    # 随机创建蓝色小球
    ran_gb_ball(blue_balls, 'blue')
    # 让绿色小球移动
    gb_ball_m(green_balls)
    # 让蓝色小球移动
    gb_ball_m(blue_balls)
    # 检查红球是否碰到蓝色、绿色小球
    r_g_b_meet()
    # 定时器
    turtle.ontimer(ball_move, 100)

主方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if __name__ == "__main__":
    # 关闭动画效果
    turtle.tracer(False)
    # 注册事件
    register_event()
    # 定制 2 种画笔形状
    for name in ['red', 'ball']:
        custom_shape(name, cell)
    # 主画笔移动墙体的左上角
    move_pos(turtle, (-300, 200))
    # 绘制墙体
    draw_blocks()
    red_ball = init_ball(rand_pos(), 'red', 'red')
    turtle.tracer(True)
    # 让红球移动起来
    ball_move()
    #
    turtle.done()

以上为此游戏程序中的每一个函数讲解。

运行后,可以控制红色小球,当遇到绿色球和蓝色球时,红色球体会变大或变小。

4. 总结

使用 turtle 模块的过程说明了一个道理,没有所谓简单的知识,如果你认为简单,那是因为你对它的认知太浅。只是学到了大家都学到的内容。

如果要真正悟透知识点的内核,需要多查阅官方文档,把所有内容吃透,并试着把这些知识向更高层面拔高。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程驿站 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Flink 1.10 升级 Flink 1.12 预期收益评估
Flink 1.12 版本在 20 年 12 月已经正式 Release,目前我们的 Flink SQL 作业的 Flink 引擎版本还是 1.10,本文主要用以评估 Flink 1.10 升级到 1.12 整体所能带来的预期收益,同时结合所需投入的成本,决定是否需要升级 Flink SQL 引擎版本到 1.12。本次升级所评估的收益包含 1.11 和 1.12 版本所带来的收益,如有理解错误,欢迎指出,一起交流。
LakeShen
2022/06/23
7230
Apache Flink 1.10.0 重磅发布,年度最大规模版本升级!
Apache Flink 社区迎来了激动人心的两位数位版本号,Flink 1.10.0 正式宣告发布!作为 Flink 社区迄今为止规模最大的一次版本升级,Flink 1.10 容纳了超过 200 位贡献者对超过 1200 个 issue 的开发实现,包含对 Flink 作业的整体性能及稳定性的显著优化、对原生 Kubernetes 的初步集成以及对 Python 支持(PyFlink)的重大优化。
Fayson
2020/02/18
1.1K0
Apache Flink 1.10.0 重磅发布,年度最大规模版本升级!
有赞实时计算 Flink 1.13 升级实践
随着有赞实时计算业务场景全部以Flink SQL的方式接入,对有赞现有的引擎版本—Flink 1.10的SQL能力提出了越来越多无法满足的需求以及可以优化的功能点。目前有赞的Flink SQL是在Yarn上运行,但是在公司应用容器化的背景下,可以统一使用公司K8S资源池,同时考虑到任务之间的隔离性以及任务的弹性调度,Flink SQL任务K8S化是必须进行的,所以我们也希望通过这次升级直接利社区的on K8S能力,直接将FlinkSQL集群迁移到K8S上。特别是社区在Flink 1.13中on Native K8S能力的支持完善,为了紧跟社区同时提升有赞实时计算引擎的能力,经过一些列调研,我们决定将有赞实时计算引擎由Flink 1.10升级到Flink 1.13.2。
有赞coder
2021/12/20
1.6K0
有赞实时计算 Flink 1.13 升级实践
正面超越Spark | 几大特性垫定Flink1.12流计算领域真正大规模生产可用(下)
我们书接上文,我们在之前的文章《正面超越Spark | 几大特性垫定Flink1.12流计算领域真正大规模生产可用(上)》详细描述了Flink的生产级别Flink on K8s高可用方案和DataStream API 对批执行模式的支持。
王知无-import_bigdata
2021/02/05
6600
Flink 1.9 特性学习和Blink SQL Parser 功能使用
本文对 Flink 1.9版本特性进行了解读(基于社区邮件组讨论),同时对Blink 开源版本 flink-sql-parser 模块进行学习了解,和大家一起交流分享。
LakeShen
2022/06/23
7180
Flink 1.9 特性学习和Blink SQL Parser 功能使用
Flink面试通关手册「160题升级版」
主要是当Flink开启Checkpoint的时候,会往Source端插入一条barrir,然后这个barrir随着数据流向一直流动,当流入到一个算子的时候,这个算子就开始制作checkpoint,制作的是从barrir来到之前的时候当前算子的状态,将状态写入状态后端当中。然后将barrir往下流动,当流动到keyby 或者shuffle算子的时候,例如当一个算子的数据,依赖于多个流的时候,这个时候会有barrir对齐,也就是当所有的barrir都来到这个算子的时候进行制作checkpoint,依次进行流动,当流动到sink算子的时候,并且sink算子也制作完成checkpoint会向jobmanager 报告 checkpoint n 制作完成。
大数据真好玩
2021/07/07
2.9K0
修改代码150万行!Apache Flink 1.9.0做了这些重大修改!(附链接)
[ 导读 ] 8月22日,Apache Flink 1.9.0 正式发布。早在今年1月,阿里便宣布将内部过去几年打磨的大数据处理引擎Blink进行开源并向 Apache Flink 贡献代码。此次版本在结构上有重大变更,修改代码达150万行,接下来,我们一起梳理 Flink 1.9.0 中非常值得关注的重要功能与特性。
数据派THU
2019/08/28
8680
修改代码150万行!Apache Flink 1.9.0做了这些重大修改!(附链接)
大数据Flink进阶(一):Apache Flink是什么
在当前数据量激增的时代,各种业务场景都有大量的业务数据产生,对于这些不断产生的数据应该如何进行有效的处理,成为当下大多数公司所面临的问题。目前比较流行的大数据处理引擎Apache Spark,基本上已经取代了MapReduce成为当前大数据处理的标准。随着数据的不断增长,人们逐渐意识到对实时数据处理的重要性。相对传统数据处理模式,流式数据处理有着更高的处理效率和成本控制要求。Apache Spark 不仅支持批数据计算还支持流式数据计算,但是SparkStreaming在底层架构、数据抽象等方面采用了批量计算的概念,其流计算的本质还是批(微批)计算。
Lansonli
2023/03/18
1.8K0
大数据Flink进阶(一):Apache Flink是什么
前沿 | 深入解读 Flink SQL 1.13
摘要:本文由社区志愿者陈政羽整理,Apache Flink 社区在 5 月份发布了 1.13 版本,带来了很多新的变化。文章整理自徐榜江(雪尽) 5 月 22 日在北京的 Flink Meetup 分享的《深入解读 Flink SQL 1.13》,内容包括:
公众号:大数据羊说
2021/08/19
1.5K0
前沿 | 深入解读 Flink SQL 1.13
Flink 1.11:更好用的流批一体 SQL 引擎
许多的数据科学家,分析师和 BI 用户依赖交互式 SQL 查询分析数据。Flink SQL 是 Flink 的核心模块之一。作为一个分布式的 SQL 查询引擎。Flink SQL 提供了各种异构数据源的联合查询。开发者可以很方便地在一个程序中通过 SQL 编写复杂的分析查询。通过 CBO 优化器、列式存储、和代码生成技术,Flink SQL 拥有非常高的查询效率。同时借助于 Flink runtime 良好的容错和扩展性,Flink SQL 可以轻松处理海量数据。
数据社
2020/07/14
1.9K0
Flink1.12集成Hive打造自己的批流一体数仓
小编在去年之前分享过参与的实时数据平台的建设,关于实时数仓也进行过分享。客观的说,我们当时做不到批流一体,小编当时的方案是将实时消息数据每隔15分钟文件同步到离线数据平台,然后用同一套SQL代码进行离线入库操作。
王知无-import_bigdata
2021/01/20
1.2K0
Flink1.12集成Hive打造自己的批流一体数仓
Flink 1.10 新特性研究
Flink 1.10 release 文档描述了一些比较重要的点,比如配置、操作、依赖、1.9 版本和 1.10 版本之间的区别,如果你准备将 Flink 升级到 1.10 版本,建议仔细看完下面的内容。
Fayson
2020/02/26
1.6K0
Flink1.14.2发布,除了log4j漏洞你还需要关注什么?
Flink1.14.2 Release版本已经在12月16日发布,主要是修复了Log4j导致的可执行任意代码的漏洞问题,但是还有一些非常重要的功能更新。
王知无-import_bigdata
2022/01/20
1.1K0
Flink重点难点:Flink Table&SQL必知必会(一)
Flink本身是批流统一的处理框架,所以Table API和SQL,就是批流统一的上层处理API。目前功能尚未完善,处于活跃的开发阶段。
王知无-import_bigdata
2021/09/22
2.2K0
Flink on Hive构建流批一体数仓
Flink使用HiveCatalog可以通过批或者流的方式来处理Hive中的表。这就意味着Flink既可以作为Hive的一个批处理引擎,也可以通过流处理的方式来读写Hive中的表,从而为实时数仓的应用和流批一体的落地实践奠定了坚实的基础。本文将以Flink1.12为例,介绍Flink集成Hive的另外一个非常重要的方面——Hive维表JOIN(Temporal Table Join)与Flink读写Hive表的方式。以下是全文,希望本文对你有所帮助。
大数据老哥
2021/02/04
4.5K0
Flink on Hive构建流批一体数仓
Flink
  1)Flink 是标准的实时处理引擎,基于事件驱动。而 Spark Streaming 是微批(Micro-Batch)的模型;
挽风
2023/10/17
7010
Flink
数据湖(十七):Flink与Iceberg整合DataStream API操作
目前Flink支持使用DataStream API 和SQL API 方式实时读取和写入Iceberg表,建议大家使用SQL API 方式实时读取和写入Iceberg表。
Lansonli
2022/07/15
2.4K0
数据湖(十七):Flink与Iceberg整合DataStream API操作
Dinky 构建 Flink CDC 整库入仓入湖
摘要:本文介绍了如何使用 Dinky 实时计算平台构建 Flink CDC 整库入仓入湖。内容包括:
文末丶
2022/05/19
4.8K0
Dinky 构建 Flink CDC 整库入仓入湖
干货 | Flink Connector 深度解析
作者介绍:董亭亭,快手大数据架构实时计算引擎团队负责人。目前负责 Flink 引擎在快手内的研发、应用以及周边子系统建设。2013 年毕业于大连理工大学,曾就职于奇虎 360、58 集团。主要研究领域包括:分布式计算、调度系统、分布式存储等系统。
大数据真好玩
2019/09/12
2.7K0
干货 | Flink Connector 深度解析
Flink 极简教程: 架构及原理 Apache Flink® — Stateful Computations over Data Streams
Apache Flink 是一个分布式流计算引擎,用于在无边界和有边界数据流上进行有状态的计算。
一个会写诗的程序员
2022/01/04
3.6K0
Flink 极简教程: 架构及原理 Apache Flink® — Stateful Computations over Data Streams
推荐阅读
相关推荐
Flink 1.10 升级 Flink 1.12 预期收益评估
更多 >
交个朋友
加入HAI高性能应用服务器交流群
探索HAI应用新境界 共享实践心得
加入[游戏服务器] 腾讯云官方交流站
游戏服运维小技巧 常见问题齐排查
加入[跨境业务] 腾讯云官方方案交流站
共享跨境方案指南 洞察行业动向
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档