程序截图、编译好的程序以及源码可以在这里找到:https://github.com/Melonl/SnakeGame_OpenGL
这是我接触OpenGL这么久一段时间以来第一次尝试开发小游戏,很多问题的解决方法都是我自己临时想出来的,可能与最优解相差甚远,这个项目算是一次尝试,同时也算是给后面的小伙伴的一个参考吧,下面开始进入正文。
OpenGL的语法、api什么的这里就不讲了,百度一搜 learn opengl一大堆教程,所以这里直接说重点的:项目中我主要写了三个类,分别是处理整个游戏逻辑的Level类、蛇Snake类和食物Food类,Level类主要的工作是启动线程,每隔一段时间更新一下蛇的状态,并且处理食物的随机生成、蛇吃到食物后的增长 这些事情。Snake类主要是储存每个蛇身方块的坐标和提供绘制蛇的方法,Food类几乎只是储存坐标和提供渲染方法,此外,Snake和Food类内都各有一个我自己封装的Shader类,Shader类里封装了一些琐碎的shader创建过程。我用了两个Shader Program分别渲染蛇和食物,各自两个shader文件,一共四个,在源码里能找到。
Snake类我用了一个stl的vector容器来储存蛇身对象,这个蛇身对象其实就是一个Cube类,Cube类只包含x 和 y值,就是代表这个蛇身方块所在的坐标,网上很多类似的贪吃蛇游戏都用链表来储存蛇身坐标,我(至少目前)觉得不够合适,(如果出于学习、练手的目的那就没什么好说的),对于蛇身来说绘制的次数要远远多于增加长度的次数(也就是吃到食物蛇身增长),众所周知(单)链表的遍历效率是很低的,基于这个原因,并且出于方便考虑,我选用了储存空间连续的vector容器。
蛇的渲染涉及到的OpenGL知识非常浅,就是画多几个矩形仅此而已,唯一比较麻烦的地方就是顶点数据的计算,在Snake类的draw()里可以看到这个极其繁琐的计算过程,大体思路就是根据蛇身包含的方块个数动态构建顶点数组,并且把颜色属性也一并构建进去,然后再动态构建顶点索引数组、传递给gpu绘制。这里再提一下蛇的移动算法,我的思路是程序接受并记录用户按下的上下左右方向键,然后根据四种方向分四个case移动蛇头,在蛇头移动之前,先把每个蛇身的坐标分别赋值为它前一个蛇身的坐标,例如蛇的坐标是0 1 2,0代表蛇头,那么在蛇头移动之前,蛇身先变化,就变成 0 0 1,然后蛇头再移动,变成 -1 0 1,这样就解决了蛇的移动问题。 至于蛇吃到食物后的增长算法,其实就是在蛇身移动前记录下蛇尾方块的坐标,在蛇移动后再往vector里添加这个蛇尾方块。
另,整个画布大小是600*600,在OpenGL空间里坐标都被映射为[-1.0,1.0],不管是蛇身还是食物方块,都是0.05宽。