用Python 进行游戏服务端开发语言可以从哪些网站,书籍入手

作为一个python开发者需要知道的关于服务器的知识 - Python - 伯乐在线
& 作为一个python开发者需要知道的关于服务器的知识
服务器的相关知识曾经让我非常困惑。我相信还有很多的Python开发者和我有着类似的遭遇。所以,请让我和你分享我知道的一切关于服务器的知识,来解开这些困惑。
HTTP: 统治万维网的协议
HTTP(超文本传输协议)是一种通信协议,它被用来发送和接收因特网上的网页以及其他数据文件。它是一套规则和相关参数的集合,这些规则和参数控制着网页和其他数据文件在因特网上的传输。
浏览器是一个HTTP客户端,因为它会发送请求到一个HTTP服务器(网页服务器),HTTP服务器随后把响应发送回客户端。HTTP监听的标准(和默认)端口是80端口,尽管其实可以使用任何的端口。这篇对HTTP进行了非常好的解释。请务必浏览一下。如果你想要钻研一下HTTP,请查看 ,它已经被多种请求注解(RFCs())所替代。你可以在搜索这些请求注解。
HTTP 服务器
因此,HTTP请求和响应有其特定的格式!当用户进入某个网站的时候,他们的浏览器与站点的网页服务器进行了连接(这个过程称之为请求)。服务器在文件系统中查询文件,并将其发送回用户的浏览器,浏览器会显示这些文件(这个过程称之为响应)。这便是HTTP协议的工作方式。看上去很简单?
动态网站并不基于文件系统中的文件,取而代之的是,当有请求到达的时候,由一个网站服务器上面运行的程序来处理。该程序会生成内容并将其返回给用户。它们可以做很多有用的事,比如显示BBS上的帖子,显示你的电子邮件,配置软件或是显示当前的时间。
不论客户端或者服务器是如何实现的,总有办法来生成有效的HTTP请求,让客户端正常工作,同样,服务器要能够理解发送给它的HTTP请求并且为所有到达的请求生成有效的HTTP响应。客户端和服务器都必须具有相互连接的能力(这种情况下会使用TCP进行可靠的连接),能够传输HTTP请求(客户端 -& 服务器)和HTTP响应(服务器 -& 客户端)。
HTTP服务器(是一个程序)会接受这些请求,并且会让你的python获取HTTP请求方法以及URI。HTTP服务器会处理很多来自图片和静态资源的请求。 那么它又是如何生成动态urls的呢?
@app.route('displaynews&name_of_category&',methods=['GET'])
@app.route('displaynews&name_of_category&',methods=['GET'])
在Flask中你可能使用过这个装饰器, 是一个python微型框架。Flask会把来自浏览器的请求和该路由进行模式匹配。但是flask是如何解析来自浏览器的http请求的呢?HTTP服务器会把动态生成的urls传递给应用服务器。哇哦!等等。。应用服务器又是什么东西呢?
Apache的 HTTPD 和nginx是两个常用的python网站服务器。
应用服务器
大多数的HTTP服务器是由C或C++写成的,所以它们不能直接执行Python脚本——在服务器和程序之间,需要一个桥梁。这个桥梁,或者说是接口,定义了程序应该如何和服务器进行交互。这就是应用服务器。动态生成的urls从网站服务器传递到应用服务器。应用服务器对url进行匹配并执行该路由对应的脚本。然后它(应用服务器)把响应返回给网站服务器,网站服务器生成一个HTTP响应,并将其返回给客户端。
对于python来讲,有很多可以用的应用服务器。 这个 列出了不同的应用服务器。起初,pyhton开发者们使用低层网关来进行部署。
通用网关接口(CGI)
这个接口,通常被称之为“CGI”,是最古老的应用服务器,它几乎被任何网站服务器所天生支持,无需专门安装。使用CGI和网站服务器进行通信的程序,需要针对每一个请求单独开启。所以每一个请求都会启动一个全新的Python解释器——这还是需要花费一点时间的——因此让整个接口只能用在低负载的情况下。
如果你想要学习如何编写一个CGI。请按照JM Marshall的这篇 去做。
mod_python
mod_python是一个Apache HTTP 服务器模块,它在服务器上面集成了Python语言。在上世纪90年代和本世纪初期,大多数的Python web应用都运行在配置了 mod_python 的Apache 上。但是,mod_python并不是标准规范。在使用mod_python时会有一些。Python web应用需要一种可持续的运作方式。
是另一种用来部署的低层网关。它们尝试解决CGI的性能问题。这些低层的网关接口不依赖特定语言。
WSGI的崛起
一个Web服务器网关接口(WSGI)服务器为运行Python web应用实现了服务器端的WSGI接口。 WSGI适合各种规模并且可以在多线程或多进程环境下工作,我们同样可以使用WSGI编写中间件。中间件对于会话处理,授权和其他很多任务都非常有用。你可以在 里面学到如何编写你自己的WSGI实现。给出了不同WSGI实现的比较。
Gunicorn and uWSGI Gunicorn 和 uWSGI
Gunicorn 和 uWSGI 是两个不同的应用服务器。是一个为UNIX设计的Python WSGI HTTP服务器。配置非常简单,和多种web框架兼容,而且它足够的快。
digitalocean的讲解了如何配置gunicorn和nginx。
是另一种备选的应用服务器。uWSGI是一个高性能,强大的WSGI服务器。uWSGI有很多可配置选项, digitalocean的 讲解了如何配置uWSGI和nginx。
Apache vs Nginx
Anturis 在他的上已经非常清晰的阐述了两者之间的不同。这篇文章解释了apache和nginx是如何工作的。
总结一下:
Apache 通过创建进程和线程来处理额外的连接。而Nginx被称为事件驱动,异步,并且非阻塞。
Apache非常强大但是Nginx非常快。Nginx可以更快呈现静态内容。
Nginx包含了先进的负载均衡以及缓存能力。
Nginx比Apache轻量级的多。
organic agency对Apache和nginx进行了基准测试。结果可以在看到。
我用的是什么
我使用Nginx因为它很快、很轻巧,并且我发现配置它更容易。Gunicorn配置起来也很简单所以我用gunicorn。uWsgi也经常被用来替代gunicorn。
请和我分享一下你的python应用倾向于使用哪一种服务器呢?
打赏支持我翻译更多好文章,谢谢!
打赏支持我翻译更多好文章,谢谢!
任选一种支付方式
关于作者:
可能感兴趣的话题
o 256 回复
关于 Python 频道
Python频道分享 Python 开发技术、相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线Python|绝不乱入的靠谱书单 - 简书
Python|绝不乱入的靠谱书单
初、中、高级的读者,都可以在这里找到满意的答案。1、2、3、4中高级阅读,5、6扩展阅读。7、8、9入门级阅读。10,思维拓展阅读。中、高级——
[法] 朱利安o丹乔(Julien Danjou) (作者)王飞龙 (译者)书  号 978-7-115-38713-4出版日期 页  数 202本书英文原版配套网址是这不是一本常规意义上Python的入门书。这本书中没有Python关键字和for循环的使用,也没有细致入微的标准库介绍,而是完全从实战的角度出发,对构建一个完整的Python应用所需掌握的知识进行了系统而完整的介绍。更为难得的是,本书的作者是开源项目OpenStack的PTL(项目技术负责人)之一,因此本书结合了Python在OpenStack中的应用进行讲解,非常具有实战指导意义。中、高级——
[美]David Beazley , [美]Brian K.Jones (作者)陈舸 (译者)书  号 978-7-115-37959-7出版日期 页  数 684《Python Cookbook(第3版)中文版》介绍了Python应用在各个领域中的一些使用技巧和方法,其主题涵盖了数据结构和算法,字符串和文本,数字、日期和时间,迭代器和生成器,文件和I/O,数据编码与处理,函数,类与对象,元编程,模块和包,网络和Web编程,并发,实用脚本和系统管理,测试、调试以及异常,C语言扩展等。本书覆盖了Python应用中的很多常见问题,并提出了通用的解决方案。书中包含了大量实用的编程技巧和示例代码,并在Python 3.3环境下进行了测试,可以很方便地应用到实际项目中去。此外,《Python Cookbook(第3版)中文版》还详细讲解了解决方案是如何工作的,以及为什么能够工作。《Python Cookbook(第3版)中文版》非常适合具有一定编程基础的Python程序员阅读参考。进 阶——
[美]Wesley J. Chun (作者)宋吉广 (译者)书  号 978-7-115-17850-3出版日期 页  数 654本书是经典的Python指导书,在第一版的基础上进行了全面升级。全书分为两个部分:第1部分占据了大约三分之二的篇幅,阐释这门语言的“核心”内容,包括基本的概念和语句、语法和风格、Python对象、数字类型、序列类型、映射和集合类型、条件和循环、文件和输入/输出、错误和异常、函数和函数式编程、模块、面向对象编程、执行环境等内容:第2部分则提供了各种高级主题来展示可以使用Python做些什么,包括正则表达式、网络编程、网络客户端编程、多线程编程、图形用户界面编程、Web编程、数据库编程、扩展Python 和一些其他材料。进 阶——
[英]Mark Summerfield (作者)王弘博 , 孙传庆 (译者)书  号 978-7-115-38338-9出版日期 页  数 518《Python 3程序开发指南(第2版 修订版)》首先讲述了构成Python语言的8个关键要素,之后分章节对其进行了详尽的阐述,包括数据类型、控制结构与函数、模块、文件处理、调试、进程与线程、网络、数据库、正则表达式、GUI程序设计等各个方面,并介绍了其他一些相关主题。全书内容以实例讲解为主线,每章后面附有练习题,便于读者更好地理解和掌握所讲述的内容。《Python 3程序开发指南(第2版 修订版)》适合于作为Python语言教科书使用,对Python程序设计人员也有一定的参考价值。中、 高级——
[爱尔兰]Igor Milovanovi? (作者)颛青山 (译者)书  号 978-7-115-38439-3出版日期 页  数 242本书是一本使用Python实现数据可视化编程的实战指南,介绍了如何使用Python最流行的库,通过60余种方法创建美观的数据可视化效果。全书共8章,分别介绍了准备工作环境、了解数据、绘制并定制化图表、学习更多图表和定制化、创建3D可视化图表、用图像和地图绘制图表、使用正确的图表理解数据以及更多matplotlib知识。本书适合那些对Python编程有一定基础的开发人员,可以帮助读者从头开始了解数据、数据格式、数据可视化,并学会使用Python可视化数据。扩展阅读——
[美]Steven Bird , [美]Ewan Klein , [美]Edward Loper(作者)  陈涛 , 张旭 , 崔杨 , 刘海平 (译者)书  号 978-7-115-33368-1出版日期 页  数 487《Python自然语言处理》是自然语言处理领域的一本实用入门指南,旨在帮助读者学习如何编写程序来分析书面语言。《Python自然语言处理》基于Python编程语言以及一个名为NLTK的自然语言工具包的开源库,但并不要求读者有Python编程的经验。全书共11章,按照难易程度顺序编排。第1章到第3章介绍了语言处理的基础,讲述如何使用小的Python程序分析感兴趣的文本信息。第4章讨论结构化程序设计,以巩固前面几章中介绍的编程要点。第5章到第7章介绍语言处理的基本原理,包括标注、分类和信息提取等。第8章到第10章介绍了句子解析、句法结构识别和句意表达方法。第11章介绍了如何有效管理语言数据。后记部分简要讨论了NLP领域的过去和未来。《Python自然语言处理》的实践性很强,包括上百个实际可用的例子和分级练习。《Python自然语言处理》可供读者用于自学,也可以作为自然语言处理或计算语言学课程的教科书,还可以作为人工智能、文本挖掘、语料库语言学等课程的补充读物。扩展阅读——
[美]Allen B. Downey (作者)许杨毅 (译者)书  号 978-7-115-38428-7出版日期 页  数 168这本书帮助那些希望用数学工具解决实际问题的人们,仅有的要求可能就是懂一点概率知识和程序设计。而贝叶斯方法是一种常见的利用概率学知识去解决不确定性问题的数学方法,对于一个计算机专业的人士,应当熟悉其应用在诸如机器翻译,语音识别,垃圾邮件检测等常见的计算机问题领域。可是本书实际上会远远扩大你的视野,即使不是一个计算机专业的人士,你也可以看到在战争环境下(二战德军坦克问题),法律问题上(肾肿瘤的假设验证),体育博彩领域(棕熊队和加人队NFL比赛问题)贝叶斯方法的威力。怎么从有限的信息判断德军装甲部队的规模,你所支持的球队有多大可能赢得冠军,在《龙与地下城》勇士中,你应当对游戏角色属性的最大值有什么样的期望,甚至在普通的彩弹射击游戏中,拥有一些贝叶斯思维也能帮助到你提高游戏水平。除此以外,本书在共计15章的篇幅中讨论了怎样解决十几个现实生活中的实际问题。在这些问题的解决过程中,作者还潜移默化的帮助读者形成了建模决策的方法论,建模误差和数值误差怎么取舍,怎样为具体问题建立数学模型,如何抓住问题中的主要矛盾(模型中的关键参数),再一步一步的优化或者验证模型的有效性或者局限性。在这个意义上,这本书又是一本关于数学建模的成功样本。入 门——
[美]Jason R. Briggs (作者)哲 (译者)书  号 978-7-115-38143-9出版日期 页  数 280本书是一本轻松、快速掌握Python编程的入门读物。全书分为3部分,共18章。第1部分是第1章到第12章,介绍Python编程基础知识,包括Python的安装和配置、变量、字符串、列表、元组和字典、条件语句、循环语句函数和模块、类、内建函数和绘图,等等。第2部分是第13章和第14章,介绍如何用Python开发实例游戏弹球。第3部分包括第15章到第18章,介绍了火柴人实例游戏的开发过程。本书语言轻松,通俗易懂,讲解由浅入深,力求将读者阅读和学习的难度降到最低。任何对计算机编程有兴趣的人或者首次接触编程的人,不论孩子还是成人,都可以通过阅读本书来学习Python编程。入 门——
[美]Zed A. Shaw (作者)王巍巍 (译者)书  号 978-7-115-35054-1出版日期 页  数 249《“笨办法”学Python(第3版)》是一本Python入门书籍,适合对计算机了解不多,没有学过编程,但对编程感兴趣的读者学习使用。这本书以习题的方式引导读者一步一步学习编程,从简单的打印一直讲到完整项目的实现,让初学者从基础的编程技术入手,最终体验到软件开发的基本过程。《“笨办法”学Python(第3版)》结构非常简单,共包括52个习题,其中26个覆盖了输入/输出、变量和函数三个主题,另外26个覆盖了一些比较高级的话题,如条件判断、循环、类和对象、代码测试及项目的实现等。每一章的格式基本相同,以代码习题开始,按照说明编写代码,运行并检查结果,然后再做附加练习。入 门——
[美]Katie Cunningham (作者)李军 , 李强 (译者)书  号 978-7-115-36209-4出版日期 页  数 235《Python入门经典》是面向Python初学者的学习指南,详细介绍了Python编程基础,以及一些高级概念,如面向对象编程。全书分为24章。第1章介绍了Python的背景和安装方法。第2章到第7章介绍了一些基本的编程概念,如变量、数学运算、字符串和获取输入。第8章到第12章介绍了更高级的主题,讨论了函数、字典和面向对象编程等。第13章到第15章介绍了如何使用库和模块,以及如何创建自己的模块。第16章到第19章介绍了使用数据,如保存到文件,使用标准格式以及使用数据库。第20章和第21章尝试了标准库以外的一些项目,在这两章中,介绍了创建动态Web站点和开发游戏。这两章并不是要成为完整的课程,而是充当学习更多知识的一个起点。第22章和第23章介绍了如何正确地保存代码,以及出错的时候如何找到解决方案。第24章介绍了读者可能会接触到哪些项目,哪些资源可以帮助读者学习更多知识,以及如何更深入地融入Python社区。思维拓展——
[美]Allen B. Downey (作者)赵普明 (译者)书  号 978-7-115-32092-6出版日期 页  数 328《像计算机科学家一样思考Python》按照培养读者像计算机科学家一样的思维方式的思路来教授Python语言编程。全书贯穿的主体是如何思考、设计、开发的方法,而具体的编程语言,只是提供一个具体场景方便介绍的媒介。《像计算机科学家一样思考Python》并不是一本介绍语言的书,而是一本介绍编程思想的书。和其他编程设计语言书籍不同,它不拘泥于语言细节,而是尝试从初学者的角度出发,用生动的示例和丰富的练习来引导读者渐入佳境。
程序员书屋公众号:programmer-book
程序员书屋QQ群:
联系我qq:
出版圈里混混一名,没事给大家推推技术书,分享分享第一手干货样章,偶尔来个赠书,发点福利。13岁Python开发者写给青少年的多人游戏编程(上) - 文章 - 伯乐在线
& 13岁Python开发者写给青少年的多人游戏编程(上)
这篇博客的作者是一名13岁的Python开发者。你可以在和上找到他。
我确定,你一定曾和你的朋友们一起玩过在线多人游戏。但是你是否想过这些游戏的内部是怎样实现的呢,游戏是怎样在计算机中运行的呢?
在这个教程中,你将通过编写一个简单的游戏来学习有关多人游戏编程。与此同时,你也将学习到面向对象程序设计的思想。
在这个教程中,你将会使用Python语言和它的PyGame模块。如果你刚接触Python或PyGame模块,你应该,将告诉你关于PyGame的基础知识。
着手开始吧
首先,你需要安装PyGame模块。你可以在这个链接上下载一个mac版的PyGame模块安装程序。如果你的系统是Mac OS 10.7或以上,请下载Lion版的安装程序,其它的,则下载Snow Leopard版本。
你也可以按以下的方法下载和安装PyGame:
如果你使用MacPorts工具,那么请用如下命令来安装:sudo port install python2.7 py27-game
如果你使用Fink,那么请使用如下命令:sudo fink install python27 pygame-py27
如果你使用Homebrew和pip,那么请在这个链接中查找下载和安装PyGame的命令。
如果你使用的是windows操作系统,那么你可以在这里找到PyGame的安装程序。
提示:如果你在上面的安装教程中遇到问题,那么请确保你在系统上安装了32位版本的Python。如果你使用的是64位的系统,那么你应该使用python2.7-32来运行Python。
最后,在这里下载我们这个项目所需的文件,(访问这个链接需要梯子),这些文件包括游戏所需的图像和声音。
我们的“游戏规则”
我们给教程中将要制作的游戏取名为“Boxes”。也许,你在学校中已经和你的朋友们在纸上玩过这个游戏了。
也许你对游戏规则并不那么熟悉,在这里,就先介绍一下游戏规则:
1.游戏的棋盘包含7×7个网格点,如果你将这些点用线段连起来,将得到6×6个立方格。
2.轮到每个玩家玩时,玩家将垂直或水平相邻的两个点用线段连接起来。
3. 如果一个玩家在网格中连接一条线后,网格中便组成了一个新格子,那么这个玩家就拥有这个新格子,并获得1分。
4 在游戏的最后,拥有格子数最多或分数最高的玩家就是胜利者。
虽然游戏的规则非常简单,但这个游戏玩起来却非常有趣,特别是当你无聊的时候。但是,如果能在线上和其他玩家玩这个游戏,是不是会更有趣呢?
面向对象程序设计简介
在我们开始编写游戏之前,先讨论一下你将在本教程中用到的面向对象程序设计思想。
面向对象程序设计,也被称为OOP,它是一个基于对象的编程方式。对象是由许多数据和与这些数据相关的逻辑组成。例如,你有一个“狗”对象,那么这个对象就包含了一些数据(例如,狗的名字、它最大的乐趣等),以及相关逻辑(例如,使狗发出叫声的指令)。
对象是由叫做“类”的模板实例化而成的,类定义了对象所包含的数据,以及这个对象能做的事情。对象的数据和它能做的事情分别称为对象的属性和方法。
方法即是一些函数,你可通过调用函数使对象完成某一任务。例如你可将car.drive()这行代码,理解为是告诉“汽车(car)”这个对象“开车(drive)”。属性是一些属于对象的变量。继续上一个例子,你的汽车“car”也许会有一个名为汽油(gas)的属性,代码car.gas = 100的意思是将汽车的汽油量设置为100.
刚才所说的两个代码操作的是一个已经存在的对象。回想我们刚才提到的,汽车(car)类是一个模板,它定义了怎样实例化一个汽车(car)对象,这个定义包括了对象的属性和方法。在对方法的定义中,你会看到对象内部的方法操作自己的代码。例如,你会看到这样的代码:self.gas=100,它不同于car.gas=100,self.gas=100的意思是汽车(car)对象告诉自己,将自己的汽油量(gas)设置为100。
OOP包含了许多内容,但是以上介绍的基础知识已经足够我们的教程了。我们用代码将Boxes游戏描述成许多对象的交互。这些对象都包含了我们在类中对其定义的若干属性和方法。当你在编写代码时,应注意,你写的类代码是从类的内部操作自身,还是操作其它外部对象。
编写一个简单的面向对象的游戏
有许多面向对象的框架可被用于我们的游戏设计。我们给Boxes游戏设计了两个对象,一个对象负责游戏的客户端,另一个对象负责游戏的服务器,现在,让我们来创建一个客户端的主类,这个类的代码将在用户启动游戏时运行。
在制作每一个游戏之前,我喜欢先为这个游戏程序创建一个文件夹。当你解压刚才下载的项目压缩文件时,将会看到一个名为boxes的文件夹。你需要将你的源文件和图像文件一起放在这个文件夹中。
在这个文件目录下,使用你最喜欢的编辑器创建一个名为boxes.py的文件(如果你没有最喜欢的编辑器,那么我推荐你在mac上使用TextEdit,或者在Windows上使用Notepad)。然后在这个文件中使用import语句:
import pygame
<div class="crayon-num" data-line="crayon-59ec3d
import pygame
这条语句导入了PyGame模块,我们在后续编码中,将使用这个模块。在进入下一步之前,你应该首先测试一下,这个模块是否已经正确导入并可以使用了。打开终端,并用cd命令,进入我们的项目文件夹,然后在终端里输入python boxes.py命令,例如,在我的机器上应输入这样的命令:
cd /Users/jmeyer/Downloads/boxes
python boxes.py
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d
cd /Users/jmeyer/Downloads/boxes&python boxes.py
如果你能成功执行这个命令,就说明PyGame模块已经正确的安装在你的电脑上了。我们就可以进入下一步教程了。
提示:如果你运行上述命令时,收到“No module named pygame”的错误提示,则说明你没有安装PyGame,或者你安装的PyGame版本和你系统中的Python版本不兼容。例如,如果你使用MacPorts来安装Python 2.7和PyGame,那么你将使用这个命令来安装他们:port install python2.7 py27-game PyGame,安装好之后,你需要保证在终端里调用2.7版本的Python:python2.7。如果运行上述代码得到这个错误:
ImportError: /Library/Frameworks/SDL.framework/Versions/A/SDL: no appropriate 64-bit architecture (see "man python" for running in 32-bit mode)
<div class="crayon-num" data-line="crayon-59ec3d
ImportError: /Library/Frameworks/SDL.framework/Versions/A/SDL: no appropriate 64-bit architecture (see "man python" for running in 32-bit mode)
就说明你需要运行32位模式的Python,例如:python2.7-32
接下来,像定义每一个类一样,在boxes.py文件中添加类定义代码:
class BoxesGame():
def __init__(self):
#put something here that will run when you init the class.
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d
class BoxesGame():&&&&def __init__(self):&&&&&&&&pass&&&&&&&&#put something here that will run when you init the class.
这段代码的第一行告诉编译器,你将创建一个名叫BoxesGame的新类。第二行定义了一个名叫__init__的方法。init两边的双下划线暗示着这是一个特殊的方法名字。事实上,这个名称__init__确定了这个类的构造方法,这个方法将在你创建或实例化一个类的对象时调用。
现在,你将在init方法中编写初始化PyGame的代码。将以下的代码紧接在原来代码中的注释部分,#put something here&#8230;:
pygame.init()
width, height = 389, 489
#initialize the screen
self.screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Boxes")
#initialize pygame clock
self.clock=pygame.time.Clock()
12345678910
#1pygame.init()width, height = 389, 489#2#initialize the screenself.screen = pygame.display.set_mode((width, height))pygame.display.set_caption("Boxes")#3#initialize pygame clockself.clock=pygame.time.Clock()
请注意输入代码的缩进格式,即刚才输入的代码都要和“#put
something here…”这段代码左对齐。你可以在这个链接中查看更多
关于Python代码缩进的内容:.
接下来我们一段一段解释刚才添加的代码:
1. 首先,你初始化了PyGame和两个变量width、height,这两个变量是用来设置我们游戏窗体的大小的。
2. 接着,用width和height变量设置窗体的宽和高。这段代码也设置了窗体的标题。
3. 最后,你初始化了PyGame的时钟,这个时钟将会用来追踪游戏中的时间。
接下来,我们添加update()方法,这个方法每隔一段时间更新一次游戏,包括重绘界面和接收用户输入。将以下的代码添加在__init__方法之后就能实现这些功能(update代码的左缩进必须和__init__相同):
def update(self):
#sleep to make the game 60 fps
self.clock.tick(60)
#clear the screen
self.screen.fill(0)
for event in pygame.event.get():
#quit if the quit button was pressed
if event.type == pygame.QUIT:
#update the screen
pygame.display.flip()
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d
def update(self):&&&&#sleep to make the game 60 fps&&&&self.clock.tick(60)&&&&&#clear the screen&&&&self.screen.fill(0)&&&&&for event in pygame.event.get():&&&&&&&&#quit if the quit button was pressed&&&&&&&&if event.type == pygame.QUIT:&&&&&&&&&&&&exit()&&&&&#update the screen&&&&pygame.display.flip()
这是一个简单的循环方法,这个方法定期清除窗体中的内容并检查用户是否想退出游戏。稍后,你会在这个方法中添加更多的内容。目前,你运行这个Python文件并不会见到什么效果,因为现在你做的仅是定义了一个名为BoxesGame的类。你还需要创建这个类的对象,然后使用这个对象运行游戏!
现在,我们已经有了update方法,让我们添加运行游戏主类的方法吧。之后,你会在这个游戏中添加一些基本的图片,例如绘制游戏中的棋盘。
在源文件的末尾添加这些代码来运行我们编写的游戏(代码的左缩进必须与文件的左缩进相同):
bg=BoxesGame() #__init__ is called right here
bg.update()
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d
bg=BoxesGame() #__init__ is called right herewhile 1:&&&&bg.update()
这三行代码体现了面向对象程序设计的一个优点:真正让程序运行的代码其实只有三行。
至此,整个源文件的内容应该是这样的:
import pygame
class BoxesGame():
def __init__(self):
pygame.init()
width, height = 389, 489
#initialize the screen
self.screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Boxes")
#initialize pygame clock
self.clock=pygame.time.Clock()
def update(self):
#sleep to make the game 60 fps
self.clock.tick(60)
#clear the screen
self.screen.fill(0)
for event in pygame.event.get():
#quit if the quit button was pressed
if event.type == pygame.QUIT:
#update the screen
pygame.display.flip()
bg=BoxesGame() #__init__ is called right here
bg.update()
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d
import pygame&class BoxesGame():&&&&def __init__(self):&&&&&&&&pass&&&&&&&&#1&&&&&&&&pygame.init()&&&&&&&&width, height = 389, 489&&&&&&&&#2&&&&&&&&#initialize the screen&&&&&&&&self.screen = pygame.display.set_mode((width, height))&&&&&&&&pygame.display.set_caption("Boxes")&&&&&&&&#3&&&&&&&&#initialize pygame clock&&&&&&&&self.clock=pygame.time.Clock()&&&&def update(self):&&&&&&&&#sleep to make the game 60 fps&&&&&&&&self.clock.tick(60)&&&&&&&&&#clear the screen&&&&&&&&self.screen.fill(0)&&&&&&&&&for event in pygame.event.get():&&&&&&&&&&&&#quit if the quit button was pressed&&&&&&&&&&&&if event.type == pygame.QUIT:&&&&&&&&&&&&&&&&exit()&&&&&&&&&#update the screen&&&&&&&&pygame.display.flip()&bg=BoxesGame() #__init__ is called right herewhile 1:&&&&bg.update()
就这样,是不是很简单?现在,让我们来运行这个游戏:
正如你看到的那样,游戏运行的结果就是看到一个令人非常印象深刻的黑色界面。
也许你现在并不理解这些代码,但是游戏的编写就像是一个战略过程。把自己想象成一个建筑设计师来编写游戏。你刚刚就为你的建筑打下了一个坚固的地基。每个雄伟的建筑都有一个良好的奠基,所以在你开始编写游戏之前,需要首先做好规划。
让我们添加另一个方法。如果你不记得什么是方法的话,那么你可以再看看教程中的“面向对象程序设计简介”这部分内容。
在游戏界面中绘制棋盘和线段
PyGame将窗体的左上角的坐标定义为(0,0)。所以我们为Boxes中的网格点定义一个坐标系统,其中(0,0)表示左上角的点,(6,6)表示右下角的点:
需要用某种方法来表示游戏中所有可能的线段。在游戏中,我们有垂直和水平的两种线段。让我们考虑一下,如何用一个列表来表示所有的线段集合,这是一个可以表示所有垂直和水平线段集合的方法:
从程序设计的角度来说,一个列表也被称为一个数组。当你的列表元素也是列表时,这个列表就被称为二维数组,例如水平和垂直线段的集合。
举一个例子,如果要表示从(0,0)点到(1,1)点水平方向上的路线,那么,就应该在“horizontal lines”这个列表中选择第0行,第0列的元素来表示。
请注意,“horizontal lines”列表有6行7列,而“vertical lines”有7行6列。(这里按照作者的代码,horizontal lines应该是7行6列,vertical lines是6行7列)
将下面两行代码添加到__init__代码中,来定义“horizontal lines”和“vertical lines”这两个数组:
self.boardh = [[False for x in range(6)] for y in range(7)]
self.boardv = [[False for x in range(7)] for y in range(6)]
self.boardh = [[False for x in range(6)] for y in range(7)]self.boardv = [[False for x in range(7)] for y in range(6)]
[valuePerItem for x in y],这个语句可以快速创建一个数组。上述代码在创建数组的同时还将数组的元素初始化为False。False代表一个空的区域。
至此,你就有了表示棋盘的方法了,接下来我们来看看怎样用代码画出这个棋盘。
首先,新建一个名为initGraphics()的方法。这个方法将被__init___方法调用,但为了使你的代码结构保持清晰,我们将载入图片的代码封装到其它方法中。在__init__方法之前,添加这个代码:
def initGraphics(self):
self.normallinev=pygame.image.load("normalline.png")
self.normallineh=pygame.transform.rotate(pygame.image.load("normalline.png"), -90)
self.bar_donev=pygame.image.load("bar_done.png")
self.bar_doneh=pygame.transform.rotate(pygame.image.load("bar_done.png"), -90)
self.hoverlinev=pygame.image.load("hoverline.png")
self.hoverlineh=pygame.transform.rotate(pygame.image.load("hoverline.png"), -90)
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d
def initGraphics(self):&&&&self.normallinev=pygame.image.load("normalline.png")&&&&self.normallineh=pygame.transform.rotate(pygame.image.load("normalline.png"), -90)&&&&self.bar_donev=pygame.image.load("bar_done.png")&&&&self.bar_doneh=pygame.transform.rotate(pygame.image.load("bar_done.png"), -90)&&&&self.hoverlinev=pygame.image.load("hoverline.png")&&&&self.hoverlineh=pygame.transform.rotate(pygame.image.load("hoverline.png"), -90)
正如你看到的那样,我们有三个垂直的线条图像:一个普通(空)线条,一个已被画过(占用)的线条和一个悬浮效果线条。将这些垂直的线条图像旋转90度,就可以表示水平的线条了。线条的图像保存在你下载的项目资源文件夹里,并且它们必须和你的python文件同处一个目录下。
你已经有了一个载入图像的方法,但是你需要调用它。猜一猜应该在哪添加调用的代码?
当你有了答案时,点击下面的“show”按钮,看看你是否答对了。
在__init__方法的末尾添加这个代码:
#initialize the graphics
self.initGraphics()
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d
#initialize the graphicsself.initGraphics()
接下来,你应该添加绘制棋盘的代码。若要循环整个棋盘上的x坐标和y坐标,你就必须在一个for循环中再嵌套一个for循环。每一个for循环可以循环x或y方向上的所有点。在__init__方法之后添加这段代码:
def drawBoard(self):
for x in range(6):
for y in range(7):
if not self.boardh[y][x]:
self.screen.blit(self.normallineh, [(x)*64+5, (y)*64])
self.screen.blit(self.bar_doneh, [(x)*64+5, (y)*64])
for x in range(7):
for y in range(6):
if not self.boardv[y][x]:
self.screen.blit(self.normallinev, [(x)*64, (y)*64+5])
self.screen.blit(self.bar_donev, [(x)*64, (y)*64+5])
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d
def drawBoard(self):&&&&for x in range(6):&&&&&&&&for y in range(7):&&&&&&&&&&&&if not self.boardh[y][x]:&&&&&&&&&&&&&&&&self.screen.blit(self.normallineh, [(x)*64+5, (y)*64])&&&&&&&&&&&&else:&&&&&&&&&&&&&&&&self.screen.blit(self.bar_doneh, [(x)*64+5, (y)*64])&&&&for x in range(7):&&&&&&&&for y in range(6):&&&&&&&&&&&&if not self.boardv[y][x]:&&&&&&&&&&&&&&&&self.screen.blit(self.normallinev, [(x)*64, (y)*64+5])&&&&&&&&&&&&else:&&&&&&&&&&&&&&&&self.screen.blit(self.bar_donev, [(x)*64, (y)*64+5])
这段代码分别循环了垂直的和水平的线段组成的列表,并检查每个线段是否被点击选中了。self.boardv[y][x]和self.boardh[y][x]返回true或false取决于这条线段是否被玩家选中了。
现在执行这个程序仍然不会有任何作用。现在你完成的代码仅定义了在drawBoard这个方法被调用时,drawBoard所要做的事情。现在让我们在update方法中添加对drawBoard的调用吧。在清空窗体的语句screen.fill(0)后添加下面的代码:
#draw the board
self.drawBoard()
#draw the boardself.drawBoard()
当然,作为一个优秀的程序员,请记住在你的代码中添加注释,解释你刚才写的代码。
现在可以运行你刚写的代码了,程序运行后,你将看到界面上出现了你绘制的网格:
每次我写绘制图片的代码时,我都会对这些代码做一点测试,因为这样很有趣,而且也能发现一些BUG。在定义self.boardh和self.boardy的代码的后面添加这个代码:
self.boardh[5][3]=True
self.boardh[5][3]=True
运行修改后的代码,你将看到,从(5,3)到(5,4)这条水平的线将会亮起:
很酷对吧?现在可以删除我们刚才添加的测试代码了。好,现在你已经成功完成棋盘的绘制了,这是我们游戏编程中的难点之一。
添加其它类型的线条
下一步,你需要找到离鼠标指针最近的一个线条,然后在那个位置绘制一个有悬浮效果的线条。
首先,在代码源文件的顶部写下这行代码,来导入我们马上用到的数学库:
import math
<div class="crayon-num" data-line="crayon-59ec3d
import math
然后在pygame.display.flip()之前,添加以下这一大段代码:
mouse = pygame.mouse.get_pos()
xpos = int(math.ceil((mouse[0]-32)/64.0))
ypos = int(math.ceil((mouse[1]-32)/64.0))
is_horizontal = abs(mouse[1] - ypos*64) & abs(mouse[0] - xpos*64)
ypos = ypos - 1 if mouse[1] - ypos*64 & 0 and not is_horizontal else ypos
xpos = xpos - 1 if mouse[0] - xpos*64 & 0 and is_horizontal else xpos
board=self.boardh if is_horizontal else self.boardv
isoutofbounds=False
if not board[ypos][xpos]: self.screen.blit(self.hoverlineh if is_horizontal else self.hoverlinev, [xpos*64+5 if is_horizontal else xpos*64, ypos*64 if is_horizontal else ypos*64+5])
isoutofbounds=True
if not isoutofbounds:
alreadyplaced=board[ypos][xpos]
alreadyplaced=False
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d
#1mouse = pygame.mouse.get_pos()&#2xpos = int(math.ceil((mouse[0]-32)/64.0))ypos = int(math.ceil((mouse[1]-32)/64.0))&#3is_horizontal = abs(mouse[1] - ypos*64) & abs(mouse[0] - xpos*64)&#4ypos = ypos - 1 if mouse[1] - ypos*64 & 0 and not is_horizontal else yposxpos = xpos - 1 if mouse[0] - xpos*64 & 0 and is_horizontal else xpos&#5board=self.boardh if is_horizontal else self.boardv isoutofbounds=False&#6try: &&&&if not board[ypos][xpos]: self.screen.blit(self.hoverlineh if is_horizontal else self.hoverlinev, [xpos*64+5 if is_horizontal else xpos*64, ypos*64 if is_horizontal else ypos*64+5])except:&&&&isoutofbounds=True&&&&passif not isoutofbounds:&&&&alreadyplaced=board[ypos][xpos]else:&&&&alreadyplaced=False
哇,好长一段代码。我们一段一段来看看这些代码吧:
1 首先,你通过PyGame的内建函数来获得鼠标指针的位置。
2 接下来,在前面的代码中,我们将网格的大小设置成了64×64,所以我们可以计算获得鼠标指针在棋盘网格中的位置。
3 你需要检查你的鼠标指针是更接近方块的上边、下边还是是方块的左边、右边。因为你需要判断用户的鼠标是悬浮在一条水平的线条上还是垂直的线条上。
4 通过is_horizontal这个变量,计算线条的新位置。
5 用boardh或boardv初始化board变量。
6 最后,你需要将悬浮效果的线画到界面上,你必须考虑是画水平的线还是垂直的线,以及这个线条画在一个方块的上边、下边、左边或是右边。你还必须检查你画的线条是否超出了棋盘的边界。如果线条超出了边界或线条已经被画过了,那么你就不需要在这样的线条上添加悬浮效果。
运行这个程序,你会惊喜地发现,当你的鼠标靠近一个线条时,线条就会亮起。
如果你像我一样,现在就一定会激动得将鼠标在屏幕上移来移去。现在就请尽情享受你的成果吧!
好,现在当用户鼠标移到网格上的某线条时,那条线就会亮起。但是,你所写的不仅仅是一个一直移动鼠标的游戏。你还需要增加这样一个功能:当鼠标点击一个线条时,这个线条就表示被玩家画过,也就是玩家拥有了这个线条。
要完成这个功能,你需要使用PyGame的内建函数:pygame.mouse.get_pressed()[0]。这个函数返回1或0取决于玩家是否点击了这个线条。在我告诉你如何实现这个功能前,你可以仔细想一想应该怎样做呢?回想一下,我们刚才是怎样使用if语句的,以及怎样在界面上绘制网格的。
将这些代码直接添加到刚才那段代码的后面:
if pygame.mouse.get_pressed()[0] and not alreadyplaced:
if is_horizontal:
self.boardh[ypos][xpos]=True
self.boardv[ypos][xpos]=True
if pygame.mouse.get_pressed()[0] and not alreadyplaced:&&&&if is_horizontal:&&&&&&&&self.boardh[ypos][xpos]=True&&&&else:&&&&&&&&self.boardv[ypos][xpos]=True
现在运行修改过的程序,如果你点击鼠标,你将会在线条悬浮的地方画上这个线条。正如你看到的,你的代码完成了这些工作:你放置的线条取决于鼠标是否被单击,以及线条是水平的还是垂直的。
这个代码有一个问题,如果你在棋盘网格的下方点击鼠标,那么我们写的游戏将崩溃。让我们看看造成这个现象的原因吧。通常,当一个错误发生时,你能在终端上看到一个错误报告,这里我们遇到的错误报告是这样的:
Traceback (most recent call last):
File "/Users/school/Desktop/Dropbox/boxes/WIPBoxes.py", line 103, in &module&
bg.update()
File "/Users/school/Desktop/Dropbox/boxes/WIPBoxes.py", line 69, in update
self.boardh[ypos][xpos]=True
IndexError: list index out of range
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d
Traceback (most recent call last):&&File "/Users/school/Desktop/Dropbox/boxes/WIPBoxes.py", line 103, in &module&&&&&bg.update()&&File "/Users/school/Desktop/Dropbox/boxes/WIPBoxes.py", line 69, in update&&&&self.boardh[ypos][xpos]=TrueIndexError: list index out of range
这个错误是因为boardh数组越界了。还记得那个isoutfobounds变量吗?这个变量可以为我们解决数组越界的问题,只要简单地像下面这样修改一行代码即可:
if pygame.mouse.get_pressed()[0] and not alreadyplaced:
#-----------to-------------
if pygame.mouse.get_pressed()[0] and not alreadyplaced and not isoutofbounds:
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d
if pygame.mouse.get_pressed()[0] and not alreadyplaced:&#-----------to-------------&if pygame.mouse.get_pressed()[0] and not alreadyplaced and not isoutofbounds:
现在,如果你在棋盘网格外点击鼠标,游戏也不会崩溃。好的,你刚才就算做了调试的工作!
在你实现游戏的服务端逻辑代码前,我们先在客户端添加一些最后的润色代码。
最后的润色
有一个问题一直困扰着我,那就是界面上网格线交叉部分的空缺。幸运的是,你可以很容易地用一个7×7大小的图片来填补这个空缺。当然,你需要一个图像文件,因此,我们现在就一口气载入这张图片以及项目中你需要使用的所有图片吧。
在initGraphics()后添加这些代码:
self.separators=pygame.image.load("separators.png")
self.redindicator=pygame.image.load("redindicator.png")
self.greenindicator=pygame.image.load("greenindicator.png")
self.greenplayer=pygame.image.load("greenplayer.png")
self.blueplayer=pygame.image.load("blueplayer.png")
self.winningscreen=pygame.image.load("youwin.png")
self.gameover=pygame.image.load("gameover.png")
self.score_panel=pygame.image.load("score_panel.png")
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d
self.separators=pygame.image.load("separators.png")self.redindicator=pygame.image.load("redindicator.png")self.greenindicator=pygame.image.load("greenindicator.png")self.greenplayer=pygame.image.load("greenplayer.png")self.blueplayer=pygame.image.load("blueplayer.png")self.winningscreen=pygame.image.load("youwin.png")self.gameover=pygame.image.load("gameover.png")self.score_panel=pygame.image.load("score_panel.png")
现在,你载入了需要的图片文件,让我们将载入的图片绘制到这49个空缺点上吧。将以下的代码添加到drawBoard():
#draw separators
for x in range(7):
for y in range(7):
self.screen.blit(self.separators, [x*64, y*64])
#draw separatorsfor x in range(7):&&&&for y in range(7):&&&&&&&&self.screen.blit(self.separators, [x*64, y*64])
好的,现在我们来测试一下游戏吧。游戏运行后,你将会看到一个更好看的网格棋盘。
接下来,让我们在游戏界面的下方放置一个平视显示器(HUD)吧。首先,你需要新建一个drawHUD()方法。
def drawHUD(self):
#draw the background for the bottom:
self.screen.blit(self.score_panel, [0, 389])
def drawHUD(self):&&&&#draw the background for the bottom:&&&&self.screen.blit(self.score_panel, [0, 389])
这段代码是在游戏界面的背景上绘制得分的面板。
让我说明一下PyGame处理字体的三个步骤:
1 首先,你需要设置一个字体以及这个字体的大小。
2 接下来,你调用font.render(“your text here”),使你输入的文本以你设置的字体呈现。
3 然后,将这些字像图片那样绘制到游戏的界面上。
现在,你已经知道怎样在界面上放置文本了,我们就可以绘制HUD的另一部分:“Your Turn”提示文字。在drawHUD()方法的尾部添加以下的代码:
#create font
myfont = pygame.font.SysFont(None, 32)
#create text surface
label = myfont.render("Your Turn:", 1, (255,255,255))
#draw surface
self.screen.blit(label, (10, 400))
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d
#create fontmyfont = pygame.font.SysFont(None, 32)&#create text surfacelabel = myfont.render("Your Turn:", 1, (255,255,255))&#draw surfaceself.screen.blit(label, (10, 400))
同样在pygame.init()的后面添加这行代码:
pygame.font.init()
<div class="crayon-num" data-line="crayon-59ec3d
pygame.font.init()
刚才添加的代码建立了字体,将字体的颜色设置成白色,然后将这些字绘制到游戏界面上。在运行游戏之前,将这行代码添加到self.drawBoard()的后面:
self.drawHUD()
<div class="crayon-num" data-line="crayon-59ec3d
self.drawHUD()
运行这个程序后,你会看到“Your Turn”这个文本出现在游戏界面的下方。如果你仔细看游戏界面的下方,你会发现精细的背景质地。
这很棒不是吗,但是你仍然需要在“Your Turn”之后添加一个指示图标,来提醒玩家轮到他们了。
在做这之前,你需要让游戏知道,这个游戏轮到谁了。所以你需要在__init__代码的尾部添加这行代码。
self.turn = True
self.turn = True
将这行代码添加到drawHUD()的尾部,以在界面上绘制指示图片。
self.screen.blit(self.greenindicator, (130, 395))
self.screen.blit(self.greenindicator, (130, 395))
现在运行游戏后,你将会看到绿色的指示器。好了,你可以把这个任务从你的未完成事项中去除了。
接下来,让我们创建每个玩家的分数文本。使用如下的代码初始化两个玩家的分数变量,将这些代码添加在__init__的末尾:
self.otherplayer=0
self.didiwin=False
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d
self.me=0self.otherplayer=0self.didiwin=False
这里,你需要添加一些其他你会在本阶段使用的变量。还记得怎样添加文本吗?现在你将重复写一些刚才写过的代码,但是使用的是不同大小的字体。将这些代码添加到drawHUD()的尾部:
#same thing here
myfont64 = pygame.font.SysFont(None, 64)
myfont20 = pygame.font.SysFont(None, 20)
scoreme = myfont64.render(str(self.me), 1, (255,255,255))
scoreother = myfont64.render(str(self.otherplayer), 1, (255,255,255))
scoretextme = myfont20.render("You", 1, (255,255,255))
scoretextother = myfont20.render("Other Player", 1, (255,255,255))
self.screen.blit(scoretextme, (10, 425))
self.screen.blit(scoreme, (10, 435))
self.screen.blit(scoretextother, (280, 425))
self.screen.blit(scoreother, (340, 435))
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d
#same thing heremyfont64 = pygame.font.SysFont(None, 64)myfont20 = pygame.font.SysFont(None, 20)&scoreme = myfont64.render(str(self.me), 1, (255,255,255))scoreother = myfont64.render(str(self.otherplayer), 1, (255,255,255))scoretextme = myfont20.render("You", 1, (255,255,255))scoretextother = myfont20.render("Other Player", 1, (255,255,255))&self.screen.blit(scoretextme, (10, 425))self.screen.blit(scoreme, (10, 435))self.screen.blit(scoretextother, (280, 425))self.screen.blit(scoreother, (340, 435))
运行程序,检查一下你的成果吧。
现在你已经完成了HUD的功能。现在还需要做一些工作来完善客户端,原谅我吧……
接下来,我们添加一个简单的变量来表示玩家所拥有的网格线。这些变量能让你跟踪玩家所拥有的方格。你需要使用这个变量正确地给玩家所拥有的方块上色并记下玩家得分。请记住,拥有最多方格的玩家将获得游戏的胜利!
首先,在__init__的末尾初始化一个数组:
self.owner = [[0 for x in range(6)] for y in range(6)]
<div class="crayon-num" data-line="crayon-59ec3d
self.owner = [[0 for x in range(6)] for y in range(6)]
和之前画网格线的方法一样,循环二维数组在屏幕上绘制玩家所拥有的网格。在类的底部添加这个方法。
def drawOwnermap(self):
for x in range(6):
for y in range(6):
if self.owner[x][y]!=0:
if self.owner[x][y]=="win":
self.screen.blit(self.marker, (x*64+5, y*64+5))
if self.owner[x][y]=="lose":
self.screen.blit(self.othermarker, (x*64+5, y*64+5))
def drawOwnermap(self):&&&&for x in range(6):&&&&&&&&for y in range(6):&&&&&&&&&&&&if self.owner[x][y]!=0:&&&&&&&&&&&&&&&&if self.owner[x][y]=="win":&&&&&&&&&&&&&&&&&&&&self.screen.blit(self.marker, (x*64+5, y*64+5))&&&&&&&&&&&&&&&&if self.owner[x][y]=="lose":&&&&&&&&&&&&&&&&&&&&self.screen.blit(self.othermarker, (x*64+5, y*64+5))
这个方法判断每一个给定的方块是否需要着色,如果需要,方法将给方块画上指定的颜色(每一个玩家都有自己的颜色)。
你还需要给游戏增加一个胜利和失败的界面。下面的方法就能完成这个功能,将它添加到类的底部:
def finished(self):
self.screen.blit(self.gameover if not self.didiwin else self.winningscreen, (0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.display.flip()
<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d<div class="crayon-num crayon-striped-num" data-line="crayon-59ec3d<div class="crayon-num" data-line="crayon-59ec3d
def finished(self):&&&&self.screen.blit(self.gameover if not self.didiwin else self.winningscreen, (0,0))&&&&while 1:&&&&&&&&for event in pygame.event.get():&&&&&&&&&&&&if event.type == pygame.QUIT:&&&&&&&&&&&&&&&&exit()&&&&&&&&pygame.display.flip()
当然,现在你还没有办法在游戏中触发这个界面。在下一部分的教程里,当你实现了游戏的服务端后,你就可以查看这个界面了。
请记住,在你添加完这些界面后,游戏的服务端就可以任意操纵客户端了。除了服务端和客户端之间的通信问题需要一点处理外,从现在开始,你不需要对客户端进行改动了。
但是,为了确保我们刚才编写的方法是正确的,我们在__init__方法的尾部调用finished()。你将看到一个向上面那幅图一样的game over的画面。
接下来要做什么呢?
这是到目前为止,本教程的源代码可在这里找到。
恭喜你!你已经完成了一个整洁而漂亮的游戏客户端。当然,虽然你出色地完成了游戏的客户端代码,但是并没有实现任何游戏的逻辑,所以我们的开发工作并没有结束。
现在你需要,教程的第二部分主要讲述游戏的服务端,随着教程,你将开始制作真正的多玩家游戏。
关于作者:
可能感兴趣的话题
我怎么也打不开,一直在加载,怎么打开三个终端呢,服务器编号是多少呢
关于伯乐在线博客
在这个信息爆炸的时代,人们已然被大量、快速并且简短的信息所包围。然而,我们相信:过多“快餐”式的阅读只会令人“虚胖”,缺乏实质的内涵。伯乐在线内容团队正试图以我们微薄的力量,把优秀的原创文章和译文分享给读者,为“快餐”添加一些“营养”元素。
新浪微博:
推荐微信号
(加好友请注明来意)
&#8211; 好的话题、有启发的回复、值得信赖的圈子
&#8211; 分享和发现有价值的内容与观点
&#8211; 为IT单身男女服务的征婚传播平台
&#8211; 优秀的工具资源导航
&#8211; 翻译传播优秀的外文文章
&#8211; 国内外的精选文章
&#8211; UI,网页,交互和用户体验
&#8211; 专注iOS技术分享
&#8211; 专注Android技术分享
&#8211; JavaScript, HTML5, CSS
&#8211; 专注Java技术分享
&#8211; 专注Python技术分享
& 2017 伯乐在线}

我要回帖

更多关于 正进行服务端处理 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信