零基础入门学习Python第一阶10图形用户界面和游戏开发

news/2024/5/24 12:07:47/ 标签: 学习, python, 开发语言, pycharm

图形用户界面和游戏开发

基于tkinter模块的GUI

GUI是图形用户界面的缩写,图形化的用户界面对使用过计算机的人来说应该都不陌生,在此也无需进行赘述。Python默认的GUI开发模块是tkinter(在Python 3以前的版本中名为Tkinter),从这个名字就可以看出它是基于Tk的,Tk是一个工具包,最初是为Tcl设计的,后来被移植到很多其他的脚本语言中,它提供了跨平台的GUI控件。当然Tk并不是最新和最好的选择,也没有功能特别强大的GUI控件,事实上,开发GUI应用并不是Python最擅长的工作,如果真的需要使用Python开发GUI应用,wxPython、PyQt、PyGTK等模块都是不错的选择。

基本上使用tkinter来开发GUI应用需要以下5个步骤:

  1. 导入tkinter模块中我们需要的东西。
  2. 创建一个顶层窗口对象并用它来承载整个GUI应用。
  3. 在顶层窗口对象上添加GUI组件。
  4. 通过代码将这些GUI组件的功能组织起来。
  5. 进入主事件循环(main loop)。

下面的代码演示了如何使用tkinter做一个简单的GUI应用。

python">import tkinter
import tkinter.messageboxdef main():flag = True# 修改标签上的文字def change_label_text():nonlocal flagflag = not flagcolor, msg = ('red', 'Hello, world!')\if flag else ('blue', 'Goodbye, world!')label.config(text=msg, fg=color)# 确认退出def confirm_to_quit():if tkinter.messagebox.askokcancel('温馨提示', '确定要退出吗?'):top.quit()# 创建顶层窗口top = tkinter.Tk()# 设置窗口大小top.geometry('240x160')# 设置窗口标题top.title('小游戏')# 创建标签对象并添加到顶层窗口label = tkinter.Label(top, text='Hello, world!', font='Arial -32', fg='red')label.pack(expand=1)# 创建一个装按钮的容器panel = tkinter.Frame(top)# 创建按钮对象 指定添加到哪个容器中 通过command参数绑定事件回调函数button1 = tkinter.Button(panel, text='修改', command=change_label_text)button1.pack(side='left')button2 = tkinter.Button(panel, text='退出', command=confirm_to_quit)button2.pack(side='right')panel.pack(side='bottom')# 开启主事件循环tkinter.mainloop()if __name__ == '__main__':main()

需要说明的是,GUI应用通常是事件驱动式的,之所以要进入主事件循环就是要监听鼠标、键盘等各种事件的发生并执行对应的代码对事件进行处理,因为事件会持续的发生,所以需要这样的一个循环一直运行着等待下一个事件的发生。另一方面,Tk为控件的摆放提供了三种布局管理器,通过布局管理器可以对控件进行定位,这三种布局管理器分别是:Placer(开发者提供控件的大小和摆放位置)、Packer(自动将控件填充到合适的位置)和Grid(基于网格坐标来摆放控件),此处不进行赘述。

使用Pygame进行游戏开发

Pygame是一个开源的Python模块,专门用于多媒体应用(如电子游戏)的开发,其中包含对图像、声音、视频、事件、碰撞等的支持。Pygame建立在SDL的基础上,SDL是一套跨平台的多媒体开发库,用C语言实现,被广泛的应用于游戏、模拟器、播放器等的开发。而Pygame让游戏开发者不再被底层语言束缚,可以更多的关注游戏的功能和逻辑。

下面我们来完成一个简单的小游戏,游戏的名字叫“大球吃小球”,当然完成这个游戏并不是重点,学会使用Pygame也不是重点,最重要的我们要在这个过程中体会如何使用前面讲解的面向对象程序设计,学会用这种编程思想去解决现实中的问题。

制作游戏窗口
python">import pygamedef main():# 初始化导入的pygame中的模块pygame.init()# 初始化用于显示的窗口并设置窗口尺寸screen = pygame.display.set_mode((800, 600))# 设置当前窗口的标题pygame.display.set_caption('大球吃小球')running = True# 开启一个事件循环处理发生的事件while running:# 从消息队列中获取事件并对事件进行处理for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseif __name__ == '__main__':main()
在窗口中绘图

可以通过pygame中draw模块的函数在窗口上绘图,可以绘制的图形包括:线条、矩形、多边形、圆、椭圆、圆弧等。需要说明的是,屏幕坐标系是将屏幕左上角设置为坐标原点(0, 0),向右是x轴的正向,向下是y轴的正向,在表示位置或者设置尺寸的时候,我们默认的单位都是[像素]。所谓像素就是屏幕上的一个点,你可以用浏览图片的软件试着将一张图片放大若干倍,就可以看到这些点。pygame中表示颜色用的是色光[三原色]表示法,即通过一个元组或列表来指定颜色的RGB值,每个值都在0~255之间,因为是每种原色都用一个8位(bit)的值来表示,三种颜色相当于一共由24位构成,这也就是常说的“24位颜色表示法”。

python">import pygamedef main():# 初始化导入的pygame中的模块pygame.init()# 初始化用于显示的窗口并设置窗口尺寸screen = pygame.display.set_mode((800, 600))# 设置当前窗口的标题pygame.display.set_caption('大球吃小球')# 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)screen.fill((242, 242, 242))# 绘制一个圆(参数分别是: 屏幕, 颜色, 圆心位置, 半径, 0表示填充圆)pygame.draw.circle(screen, (255, 0, 0,), (100, 100), 30, 0)# 刷新当前窗口(渲染窗口将绘制的图像呈现出来)pygame.display.flip()running = True# 开启一个事件循环处理发生的事件while running:# 从消息队列中获取事件并对事件进行处理for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseif __name__ == '__main__':main()
加载图像

如果需要直接加载图像到窗口上,可以使用pygame中image模块的函数来加载图像,再通过之前获得的窗口对象的blit方法渲染图像,代码如下所示。

python">import pygamedef main():# 初始化导入的pygame中的模块pygame.init()# 初始化用于显示的窗口并设置窗口尺寸screen = pygame.display.set_mode((800, 600))# 设置当前窗口的标题pygame.display.set_caption('大球吃小球')# 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)screen.fill((255, 255, 255))# 通过指定的文件名加载图像ball_image = pygame.image.load('./res/ball.png')# 在窗口上渲染图像screen.blit(ball_image, (50, 50))# 刷新当前窗口(渲染窗口将绘制的图像呈现出来)pygame.display.flip()running = True# 开启一个事件循环处理发生的事件while running:# 从消息队列中获取事件并对事件进行处理for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseif __name__ == '__main__':main()
实现动画效果

说到[动画]这个词大家都不会陌生,事实上要实现动画效果,本身的原理也非常简单,就是将不连续的图片连续的播放,只要每秒钟达到了一定的帧数,那么就可以做出比较流畅的动画效果。如果要让上面代码中的小球动起来,可以将小球的位置用变量来表示,并在循环中修改小球的位置再刷新整个窗口即可。

python">import pygamedef main():# 初始化导入的pygame中的模块pygame.init()# 初始化用于显示的窗口并设置窗口尺寸screen = pygame.display.set_mode((800, 600))# 设置当前窗口的标题pygame.display.set_caption('大球吃小球')# 定义变量来表示小球在屏幕上的位置x, y = 50, 50running = True# 开启一个事件循环处理发生的事件while running:# 从消息队列中获取事件并对事件进行处理for event in pygame.event.get():if event.type == pygame.QUIT:running = Falsescreen.fill((255, 255, 255))pygame.draw.circle(screen, (255, 0, 0,), (x, y), 30, 0)pygame.display.flip()# 每隔50毫秒就改变小球的位置再刷新窗口pygame.time.delay(50)x, y = x + 5, y + 5if __name__ == '__main__':main()
碰撞检测

通常一个游戏中会有很多对象出现,而这些对象之间的“碰撞”在所难免,比如炮弹击中了飞机、箱子撞到了地面等。碰撞检测在绝大多数的游戏中都是一个必须得处理的至关重要的问题,pygame的sprite(动画精灵)模块就提供了对碰撞检测的支持,这里我们暂时不介绍sprite模块提供的功能,因为要检测两个小球有没有碰撞其实非常简单,只需要检查球心的距离有没有小于两个球的半径之和。为了制造出更多的小球,我们可以通过对鼠标事件的处理,在点击鼠标的位置创建颜色、大小和移动速度都随机的小球,当然要做到这一点,我们可以把之前学习到的面向对象的知识应用起来。

python">from enum import Enum, unique
from math import sqrt
from random import randintimport pygame@unique
class Color(Enum):"""颜色"""RED = (255, 0, 0)GREEN = (0, 255, 0)BLUE = (0, 0, 255)BLACK = (0, 0, 0)WHITE = (255, 255, 255)GRAY = (242, 242, 242)@staticmethoddef random_color():"""获得随机颜色"""r = randint(0, 255)g = randint(0, 255)b = randint(0, 255)return (r, g, b)class Ball(object):"""球"""def __init__(self, x, y, radius, sx, sy, color=Color.RED):"""初始化方法"""self.x = xself.y = yself.radius = radiusself.sx = sxself.sy = syself.color = colorself.alive = Truedef move(self, screen):"""移动"""self.x += self.sxself.y += self.syif self.x - self.radius <= 0 or \self.x + self.radius >= screen.get_width():self.sx = -self.sxif self.y - self.radius <= 0 or \self.y + self.radius >= screen.get_height():self.sy = -self.sydef eat(self, other):"""吃其他球"""if self.alive and other.alive and self != other:dx, dy = self.x - other.x, self.y - other.ydistance = sqrt(dx ** 2 + dy ** 2)if distance < self.radius + other.radius \and self.radius > other.radius:other.alive = Falseself.radius = self.radius + int(other.radius * 0.146)def draw(self, screen):"""在窗口上绘制球"""pygame.draw.circle(screen, self.color,(self.x, self.y), self.radius, 0)
事件处理

可以在事件循环中对鼠标事件进行处理,通过事件对象的type属性可以判定事件类型,再通过pos属性就可以获得鼠标点击的位置。如果要处理键盘事件也是在这个地方,做法与处理鼠标事件类似。

python">def main():# 定义用来装所有球的容器balls = []# 初始化导入的pygame中的模块pygame.init()# 初始化用于显示的窗口并设置窗口尺寸screen = pygame.display.set_mode((800, 600))# 设置当前窗口的标题pygame.display.set_caption('大球吃小球')running = True# 开启一个事件循环处理发生的事件while running:# 从消息队列中获取事件并对事件进行处理for event in pygame.event.get():if event.type == pygame.QUIT:running = False# 处理鼠标事件的代码if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:# 获得点击鼠标的位置x, y = event.posradius = randint(10, 100)sx, sy = randint(-10, 10), randint(-10, 10)color = Color.random_color()# 在点击鼠标的位置创建一个球(大小、速度和颜色随机)ball = Ball(x, y, radius, sx, sy, color)# 将球添加到列表容器中balls.append(ball)screen.fill((255, 255, 255))# 取出容器中的球 如果没被吃掉就绘制 被吃掉了就移除for ball in balls:if ball.alive:ball.draw(screen)else:balls.remove(ball)pygame.display.flip()# 每隔50毫秒就改变球的位置再刷新窗口pygame.time.delay(50)for ball in balls:ball.move(screen)# 检查球有没有吃到其他的球for other in balls:ball.eat(other)if __name__ == '__main__':main()

上面的两段代码合在一起,我们就完成了“大球吃小球”的游戏,准确的说它算不上一个游戏,但是做一个小游戏的基本知识我们已经通过这个例子告诉大家了,有了这些知识已经可以开始你的小游戏开发之旅了。其实上面的代码中还有很多值得改进的地方,比如刷新窗口以及让球移动起来的代码并不应该放在事件循环中,等学习了多线程的知识后,用一个后台线程来处理这些事可能是更好的选择。如果希望获得更好的用户体验,我们还可以在游戏中加入背景音乐以及在球与球发生碰撞时播放音效,利用pygame的mixer和music模块,我们可以很容易的做到这一点,大家可以自行了解这方面的知识。事实上,想了解更多的关于pygame的知识,最好的教程是pygame的官方网站,如果英语没毛病就可以赶紧去看看啦。 如果想开发3D游戏,pygame就显得力不从心了,对3D游戏开发如果有兴趣的读者不妨看看Panda3D。


http://www.ppmy.cn/news/1434599.html

相关文章

Python-VBA函数之旅-getattr函数

目录 一、getattr函数的常见应用场景&#xff1a; 二、getattr函数使用注意事项&#xff1a; 1、getattr函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;https://blog.csdn.net/ygb_1024?spm1010.21…

Linux进程详解三:进程状态

文章目录 进程状态Linux下的进程状态运行态-R阻塞态浅度休眠-S深度睡眠-D暂停状态-T暂停状态-t 终止态僵尸-Z死亡-X 孤儿进程 进程状态 进程的状态&#xff0c;本质上就是一个整型变量&#xff0c;在task_struct中的一个整型变量。 状态的存在决定了你的后续行为动作。 Linu…

【Linux】日志分析与管理

作为一个运维&#xff0c;如果不会看日志&#xff0c;就好比是冬天刚刚用热水泡完了脚&#xff0c;接着就立马让人把水喝掉。 目录 一、Inode介绍 1.1 什么是inode 1.2 inode表内容 1.3 查看inode号的方式 二、日志分析 2.1 日志的用途 2.2 日志的分类 2.3 日志级别 2…

maya显示隐藏 动画长度

目录 大纲视图&#xff0c;选择节点&#xff0c;H控制显示与隐藏 使用Viewport显示/隐藏 脚本控制显示/隐藏 获取动画长度python脚本 大纲视图&#xff0c;选择节点&#xff0c;H控制显示与隐藏 使用Viewport显示/隐藏 这是最直观的方法&#xff0c;适合临时隐藏Mesh以便专…

EelasticSearch的docker安装-----》es客户端使用!!!

1.Docker安装 docker run -d --name es7 -e ES_JAVA_POTS"-Xms256m -Xmx256m" -e "discovery.typesingle-node" -v /opt/es7/data/:/usr/share/elasticsearch/data -p 9200:9200 -p 9300:9300 elasticsearch:7.14.02.客户端UI工具&#xff0c;Edge浏览器…

北航计算机软件技术基础课程作业笔记【4】

题目&#xff08;好像以前没加&#xff09; 二叉树与哈希表 作业 1.二叉树前序遍历结果 二叉树结构为 代码实现中序后序推理前序表达式 #include <iostream> #include <stack> #include <string> #include <vector> #include <deque> ​ // …

Laravel 6 - 第十五章 验证器

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

webview的使用方法和后退键的处理

WebView是一个能够显示网页内容的控件&#xff0c;通常用于Android或iOS应用程序中嵌入网页。下面我将分别说明WebView在Android和iOS中的使用方法&#xff0c;以及如何处理后退键。 Android中的WebView使用方法 添加WebView到布局文件中 在你的布局XML文件中添加WebView控件…

Linux 的情况下实现贪吃蛇 -- 第二十八天

1.keypad(stdsrc,1) 参数表示是否接收&#xff0c;1表示接收指令 2.思路&#xff1a;初始化initNcurses()&#xff0c; 封装地图函数实现地图gamePic&#xff08;&#xff09; 分三部分实现&#xff1a;2.1: 在第0行&#xff1a;打印 "--"," | "和&q…

【JavaScript编程实操14】DOM实操_回到顶部

前言 本次主要是针对Javascript阶段的DOM实操方面的练习&#xff0c;本次主要实现当页面内容过多时&#xff0c;可以点击按钮&#xff0c;快速回到页面顶部的效果。这次的实现逻辑比较简单&#xff0c;主要是应用函数实现页面的回到顶部功能&#xff0c;this.scrollTo(0, 0)可以…

完美解决多种情况下的 java.lang.NullPointerException 的异常

文章目录 1. 复现错误2. 分析问题3. 解决问题1. 复现错误 在工作中,经常会遇见java.lang.NullPointerException的异常,这种异常千奇百怪,但明确一点的是:它是空指针异常,也称之为NPE异常,如下代码所示: @Setter @Getter @Accessors(chain = true) public class Student…

10.Java集合汇总

文章目录 1. Java集合概述1.1 Java集合框架概述1.2 Collection接口继承树1.3 Map接口继承树 2. Collection接口2.1 Collection接口方法 3 Iterator迭代器接口3.1 Iterator接口的方法3.2 foreach循环 4 List接口4.1 List接口方法4.1 ArrayList4.2 LinkedList4.3 Vector4.4 面试题…

【vim】折叠代码

目录 简介操作创建折叠删除折叠打开或关闭折叠在折叠间移动简介 Vim编辑器中可以使用 foldmethod 选项设置折叠方法。 将 foldmethod 设置为 manual 以外的值时,将删除所有折叠并创建新折叠。切换到 manual 方法不会删除现有的折叠。由此可以先用自动定义折叠,然后手动更改它…

redmibook 14 2020 安装 ubuntu

1. 参考博客 # Ubuntu20.10系统安装 -- 小米redmibook pro14 https://zhuanlan.zhihu.com/p/616543561# ubuntu18.04 wifi 问题 https://blog.csdn.net/u012748494/article/details/105421656/# 笔记本电脑安装了Ubuntu系统设置关盖/合盖不挂起/不睡眠 https://blog.csdn.net/…

[蓝桥杯 2018 省 A] 航班时间

题目链接&#xff1a;航班时间 显然&#xff1a;去程时间飞行时间时差&#xff0c;回程时间飞行时间-时差 列方程组可知&#xff1a;飞行时间&#xff08;去程时间回程时间&#xff09;/2 本道题目还有一个难点在于如何读入和输出&#xff1a;可以采用scanf&#xff08;&…

el-select下拉框远程搜索且多选时,编辑需要回显的一个简单案例

前端业务开发中不管使用vue2~3&#xff0c;还是react&#xff0c;angular各种前端技术栈&#xff0c;经常会遇到这种业务。一个下拉框Select中&#xff0c;不仅需要需要支持远程模糊搜索&#xff0c;还需要支持多选。并且在编辑时&#xff0c;还能正常把已经多选好的内容回显到…

有哪些网络连接方式?

网络连接方式多种多样&#xff0c;大家常常对各类连接方式感到困惑&#xff0c;难以区分。以下是从连接形式和用途的角度分类的几种主要网络连接方式&#xff1a; 按连接形式分类 1、有线连接&#xff1a; 以太网连接&#xff1a;使用双绞线或同轴电缆&#xff0c;常见于局域…

「JavaEE」线程状态

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;JavaEE &#x1f387;欢迎点赞收藏加关注哦&#xff01; 线程状态 &#x1f349;start 和 run 的区别&#x1f349;终止线程&#x1f349;join & 阻塞状态&#x1f349;线程六大状态 &…

开源AI Agent框架的选择

在选择开源AI Agent框架时,首先需要考虑的是框架的开发优先级、功能特性以及社区支持情况。SuperAGI是一个开发者优先的开源自主AI代理框架,它使开发人员能够快速可靠地构建、管理和运行有用的代理12。这表明SuperAGI可能是一个适合需要快速迭代和高度自定义能力的项目的良好…

Springboot+Vue项目-基于Java+MySQL的图书馆管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…