事情是这样的。
毛概实践作业有个专业实践,要结合专业,做点和毛概相关的东西出来。大家都以为是五月底截止,没想到前几天忽然说这个月17号就截止了,都被吓到了。于是连续刚了好几晚上,总算及时做出来了。
这次没有用之前常用的Unity3D,这东西不适合做2D游戏,用起来虽然简单,但想定制化需要做一些操作,就有点麻烦。之前关注了一个公众号,叫Charles的皮卡丘。作者用python的pygame模块做了许多2D小游戏,而且全部在我当时有跟着看,但都是走马观花,趁着这个机会,正好仔细学一学,给自己个挑战。
下面先来看个通关视频,看完就知道这个项目做了点啥了。
可以看到这个游戏一共三关,一共有三种怪物。人物的武器只有一种,但可以捡拾随机刷新的回旋镖来秒杀怪物。
下面来说说这游戏是怎么做出来的。
首先,我不会pygame。为了快速入门,我选择直接看现成的项目代码,也就是之前提到的Charles的皮卡丘的游戏代码。在他的公众号获得github地址后(https://github.com/CharlesPikachu/Games),我查看了其中两个,一个是贪吃蛇,一个是打地鼠。
贪吃蛇逻辑比较简单,先看的这个。从这个项目里,我学会了pygame的基本流程:
首先是一个死循环,然后里面是捕捉各种事件的for-each循环,在这个循环前后都可以做图形的绘制和逻辑操作,而后是update,将上述的代码更新显示。这个死循环每次循环都会播放一帧,如果不加以控制事件,就会按照程序运行的速度播放,这是不太好的,有时会导致播放速度的波动。在贪吃蛇里用的方法是
第一行写在死循环外,第二行在update之后执行。tick函数里的参数是设置好的帧数,例如填写60,则会强制按照一秒60帧来运行游戏,解决了直接While循环的问题。
然后,我发现这个项目里的游戏物体都是用一个类来封装的,且无一例外,全都继承了父类Sprite(精灵类)。不太懂什么意思,但我一边看这个代码,一边写demo,的确能体会到封装成类的好处,大大方便了游戏的交互,使游戏主逻辑清晰明了。Sprite类究竟有什么好处,现在我还不得而知。在第二个项目里,Sprite类可以用来做碰撞检测,非常方便。我的游戏里也只是用到了这一个功能而已。
(碰撞检测的例子。判断主角和刷新出的回旋镖是否碰撞,即是否吃到。)
此外,还有一些游戏必备要素的代码写法。
音乐、音效的播放:
(音效)
(音乐)
文字:
(读取字体,设置大小。设置文本。通过rect设置位置。在循环中绘制。)
各种事件,如鼠标事件、键盘事件、自定义间隔事件等等。
上面的这些,每次新学到后我都记录了下来。因为比较零碎,就没有仔细分类,统统记在onenote里的一页中。
这样做,学习代码速度还是很快的,只需要记住学了什么,不用去记实现的细节,写的时候随时参考就行了。这一页纸就像我大脑的U盘,需要用的时候,再提取到内存里。
然后我发现,差不多可以开始写了。
写的时候还是有不少困难的,刚学,东西记不住,总需要查查查,但我写完整个项目后,发现经过不断地重复,我已经不再依赖之前的记录,基本可以想到什么写什么了。感觉这种学习方法还是挺有效的。
因为游戏比贪吃蛇什么的还是复杂一点的,一定要设计好类的结构,设计好每个文件要做什么。我以前写这个就是想到哪写到哪,经常写到一半才发现设计有问题,要重新结构......于是这次采取的方式是,先建立好各个文件,在每个文件里注明要做什么事,要写哪些类哪些方法,都各自要实现什么功能。
大概用了一个多小时的完成所有的注释。而后,我们有了整个项目框架的大体概念,跟着注释写就快得多了。
差不多是每一个画面写一个函数,里面是死循环,然后加一些变量来控制跳转,一个游戏就这么写完了。这种写代码方式还是值得推荐的,在自己一个人写代码,不想画类图写文档的时候,可以起到替代的作用。
此外,还借鉴那两个项目,使用了配置文件cfg.py来记录常量,发现非常爽,写出来干净整洁,还便于修改。
总体来说游戏挺简单,但整个制作的过程我觉得还是让我有不少收获的。
具体代码细节就不赘述了,有兴趣可以下载了看一看,里面也有打包好了的exe文件,直接就能玩。
项目地址:https://gitee.com/worldTester/Game