[OpenGL] 游戏开发的简单demo

来源:互联网 发布:一线城市 知乎 编辑:程序博客网 时间:2024/06/10 12:12

完成时间:2016年08月23日(大三上)

博客时间:2017年04月19日

转载请注明作者 _(:3 」∠)_ RyuZhihao123 (Northwest A&F University,985/211)

程序截图:







简介:

       这个程序是我大二为《软件工程》课程的作业而编写的,采用C++/OpenGL开发。因为只是一个作业,实现的比较简单,但是还是运用了一些设计思想,比较有参考价值吧。现在过了将近半年才回来填这个坑,主要也是因为涉及到的内容太多了(其实是我太懒 (。・`ω´・)

       这篇博客可能更多地侧重于游戏的设计思想,如果想要交流欢迎评论或者私信哦


游戏开发的几点重要策略:

1.   高效的游戏循环(Game Loop)

     方法一:一个最简单粗暴但相当劣质的处理方式是:用一种能跑多快跑多快的方式进行游戏循环。简单的用代码表示一下:

int main()   {while(true)    // 一种不好的方式{processInput();  // CPU处理输入update();        // CPU修改状态render();       // GPU渲染画面}}
       不难发现,在快的机器上,游戏循环可能快得令玩家看不清游戏在做什么;在慢的机器上,游戏则会变得又慢又卡。

       方法二:我们稍加一下改进:你想让时间以60fps的速度运行,也就是间隔MS_PER_UPDATE=16毫秒进行一个游戏循环,那么则可以以一个稳定的帧率来跑游戏。What you should do is to wait for next frame.简单的用代码表示一下:

int main(){while(true)  // 维持相对稳定的帧率的方法{double start = getCurrentTime();processInput();update();render(); // 等待一段时间,凑够16mssleep( MS_PER_UPDATE - (getCurrentTime() - start));}}

       这种方法,通过引入的一个sleep()方法帮助我们维持了一个相对稳定的fps。但是,我们也能发现一个问题:若每次实际用于更新的时间长于固定的间隔时间MS_PER_UPDATE,那么游戏同样会变慢。例如,当需要16ms以上的时间去更新fps=16ms的游戏时,就会无法维持运行速度。

      
       方法三: 让我们试一下稍微复杂点的方法。为了解决方法二中出现的问题,我们以这一帧与上一帧的实际时间间隔来作为更新步长。帧处理花费的实际时间越长,这个步长也就越长。这个方法舍弃了固定的MS_PER_UPDATE,而是采用实际间隔时间elapsed来作为更新依据。这个方法使得游戏总会越来越接近于实际的时间。因此也被称为变值时间步长。

int main(){double lastTime = getCurrentTime();while(true)  // 维持相对稳定的帧率的方法{double current = getCurrentTime();double elapsed = current - lastTime;processInput();update(elapsed);render();lastTime = current;}}
     这种游戏循环虽然有了很大的提高,但是也有潜在的问题(可以参考给出的参考资料)。

     方法四:最后的改进,通过引入一个新的变量lag来表示游戏时钟相对于现实时间落后的差量。接着用一个内部循环更新游戏,每次以固定时长MS_PER_UPDATE进行,直到追上现实时间(此处的MS_PER_UPDATE不是视觉上的帧速,而是更新游戏update()的间隔)

int main()   // 一个比较好的方案:可以追回因为render()落后的时间{double lastTime = getCurrentTime();double lag = 0.0;while(true){double current = getCurrentTime();double elapsed = current - lastTime;lastTime = current;lag += elapsed;processInput();// 内部循环:以固定时长更新游戏以赶上落后的时间。while(lag >= MS_PER_UPDATE){double startUpdate = getCurrentTime();update();lag -= MS_PER_UPDATE;sleep(MS_PER_UPDATE - (getCurrentTime()-startUpdate));}render();}}



2. 场景管理Scene Management

        3D游戏中场景管理的方法有很多:四叉树、八叉树、BSP树、KD树等。方法各有优劣,适用的情形各不相同。但是原理较为复杂,这里也不过多描述,需要的可以自己去google。


        例如:使用八叉树/kd树,可以以很高的效率进行空间查询:

                 (1) 邻近查询(proximity query):如查询玩家周围的npc、掉落物品等。

                 (2) 可见性判断(view frustum culling):剔除不可见的物体

                 (3) 粗略的碰撞检测:找到潜在的可能碰撞的对象。


       下图便是采用k-d树的空间划分结构,为每个单位划分一个区域。


3. 人工智能单位 AI

        其实,对于AI单位的管理,应当归于Scene Management。但是AI单位有自己的特殊之处,受到攻击时会追击、拉开距离后停止追赶。

这里的话,需要进行碰撞、攻击判定等。可能会用到的技术有:AABB包围盒等。


4. 大规模地形渲染

         这是一个比较复杂的东西,但是如果使用下面提到的技术会大大提高你的渲染效率。我们在render large terrains时,经常采用的便是LOD(level of detail)的技术,根据距离确定细节层次。

         详情可以看一下我翻译的另一片博客:How to rendering large terrains


5. 参考资料:

    1.  [Book] Game Programming Patterns - Robert Nystrom

    2.  [LINK] http://gameprogrammingpatterns.com/game-loop.html

    3.  [LINK]http://www.koonsolo.com/news/dewitters-gameloop/


6. 写在后面

      希望我的文章,能够为有志于开发游戏的同志有所帮助。我也还只是一个普通的本科生,欢迎不幸点开这篇文章的诸位大神批评指正!!!

      这是一个比较简单的demo,欢迎评论或者私信讨论。另外我之前做的一个游戏仿制《minecraft》的资料还有演示程序可以在我的其他博客中翻到~ (ง •̀_•́)ง。   

       我使用OpenGL仿制的一款《Minecraft》:仿制《Minecraft》


2 0
原创粉丝点击