WIP(Working In Progress)是我初学游戏引擎开发时候开发的一个2D游戏引擎,当时计划为它实现类似Unity一样的编辑器,具有和Unity相似的工作流,但是由于水平不够,走了很多弯路,闭门造车,做了很多错误的设计,导致很多地方反人类和难以维护,加之时间有限,所以已经停止了对它的继续开发。由于停止了开发,又不想把所有资料都全部搞丢,所以把在开发中学到的东西,和一些自己的思考都记录一下。以便后可以参考。

他最后可以实现这些功能,不过实现起来远比成熟的引擎蛋疼得多:

  • 脚本游戏编程
  • 基本的2D游戏(我曾经用这个东西做过flappy bird和一个简单的RPG游戏(由于没有写编辑器,制作起来非常耗时特别是帧动画和布置场景的时候))
  • 一些2Ddemo(之前上课的几个作业一直用这个做)
  • 简单的OpenGL shader
  • 简单的3D呈现

当时就选择了脚本流,因为之前接触过一段时间的Lua,所以脚本语言也直接选择了Lua。脚本的嵌入采用了很简单的思想,没有去导出c++类,而是简单实现了lua中的类,再把所有的c++对象都映射为一个lua对象中的指针,这样做的效率也许不高,但是后来也没有遇到什么大问题,只是有的时候会不方便,而比较棘手的就是对象销毁问题,我在哪些对象需要自动销毁,那些对象不需要上,想了很久,最终也没有理出一个完全彻底的方案。另外,我的脚本系统仅仅是执行游戏逻辑,我在主循环中使用一个函数每帧都调用Lua脚本的入口函数,从而驱动整个脚本系统。

至于基于组件的游戏对象,和数据驱动基本上全靠Lua和XML。场景保存到XML文件中的,每个场景中的对象就是一个XML结点,而读取场景则选择了在lua中实现,一切的一切都全仰仗于这个函数:

function System.genertate_component_by_name(component_name)
s = "local _ = require \""..component_name.."\";return _:new()"
return loadstring(s)
end

也就是说全靠lua的loadstring函数。我的每一个组件都是一个Lua脚本,这些脚本继承于一个基类,当然也都是Lua实现的,这些,我都是借鉴自Unity的脚本系统中我看得懂的部分,所以部分看起来和Unity的很类似。虽然简单,但是应该说,我从这次实现尝试中学到的东西还是不少,至少解了了一些很有用的概念。对Lua的了解也深入了一步。

渲染是我这次尝试中最失败的部分,因为首先我并不熟悉OpenGL,而且在此之前我基本只使用Opengl的老渲染管线渲染图像。所以最开始的时候,我的渲染系统中导出都是glbegin,glend,后来随着我的深入学习,我将那些地方全部改成了gldrawelements或者gldrawarray来渲染,但是思想依然是固定渲染管线的思想。在我的渲染系统中,每次渲染一个四边形,都会绑定一个纹理上去,然后把这个东西的顶点数据和纹理坐标以及纹理id打包存到一个容器v中,直到一帧结束,将v中的所有东西全部取出来,一个一个的调用drawelements,然而这对渲染的效率并没有什么提升,多次drawcall依然是多次drawcall,固定管线依然是固定管线,对于所谓的多线程也完全没什么用处。后来我准备在这个系统上开刀,试图把所有的drawcall合并,然而这将会直接导致整个系统的重写。后来逐渐深入学习了Opengl,想使用可编程管线来渲染3D网络,强制加入了Shader功能,然而这样的行为并不好,而且很多时候如果2D3D一起渲染会产生问题,也就是说,这个渲染系统仅仅只支持2D渲染,如果想渲染3D图形,对不起只能用OpenGL,连封装都没有……而当时使用在渲染2D对象的时候,幸好用了mesh的概念,而不是直接拉四个点去……

场景管理其实那时候是没有那个概念的,2D游戏计算量没到,当然不会去考虑场景管理优化之类的,Scene类唯一有的功能就是分了3个层,一个层用来装object,一个用来装UI,剩下的用来装volumes。因为当时考虑到,object的更新和UI的更新并不是一样频繁的,至于volumes,本来是想用来存放一些阻挡体积,碰撞体积,就和UE里面的volume差不多的,但是由于一些硬伤,这些东西知道最后也没有能够加进去。

关于物理,我并不太懂物理,wip当前仅支持基本的刚体物理,物理部分主要是我的一个同学帮助我完成的,我仅仅介入他写好的功能。物理上,我遇到的问题就是更新。物理引擎为我提供的东西主要就是一个body,我把这个body作为我的object的一个组件。于是在更新的时候,我就要不断地将当前的位置写入body更新后在写出到object,这样做我一直觉得特别低效。不过还好这个东西并不会涉及到lua交互而是批量更新。

动画方面,我实现了帧动画,以及尝试嵌入了spine这个骨骼动画插件。帧动画就是很简单的将一张纹理上的各个区域一直做变换,不停的播放。帧动画我实现了一个叫做clip的文件,这个文件记录一个动画clip的每一帧的信息,包括uv和帧数等等。然而在实际使用的时候,没有编辑器,手动修改大批这样的数据是及其痛苦的。关于骨骼动画,我使用了spine来嵌入,但是这个嵌入由于渲染部分的设计问题,效果并不是很好,由于我的每一个对象渲染出来都是一个矩形区域,所以我只能先将骨骼动画结果渲染到一个fbo上,然后由这个fbo渲染到矩形上,而问题就在于这个矩形区域又和碰撞矩形挂钩,而一个骨骼动画对象在运动时往往需要一张最大的矩形来容纳他的所有运动范围,所以这个矩形应该尽量能够框住整个运动对象,但是碰撞却不是,骨骼动画的碰撞需要拆分到各个部件来计算!所以无论我怎么修改骨骼动画的嵌入方式,也无法改善碰撞和渲染的耦合,唯一的方案就是重写。而这也是我放弃了wip的主要原因之一。后来我心血来潮在其中自己实现了一个骨骼动画系统,但是这个系统的设计是不完备的,也就是它只能播放骨骼动画,而没有考虑动画数据来源。

声音部分其实我不是很懂,我使用了OpenAL来驱动声音,而声音文件解析则采用了libogg。声音我基本上参考来参考去实现了流播放和整体加载播放的基本能力。剩下的研究就不多了。

其实在整个实现中遇到的最大问题还是文本渲染,首先我完全不懂文字的造型什么的,所以我使用了freetype,借助freetype造型好文字后,我则将其加载到纹理进行渲染。这个系统应该是最不完善的一个系统把。

UI系统本来最开始是没有的,但是我有段时间跟着老师做东西,做了个基于of的简uii系统。想了一下直接就把能用的控件移植到引擎中来了。UI部分还是基于回调的UI,思想比较老旧,但是基本能用。我在demo里面就展示了几个可用的UI控件。

其他的一些比较基础的库,算法数据机构上我一开始还在考虑要不要使用stl还是使用boost,但是后来发现一使用起stl就停不下来。数学库,则是我之前参考UE的数学库自己半抄半写的,因为总是读书少瞎想多,所以当年还真的特别担心完全自己瞎写数学库会拉低效率,然后想到UE的源代码,于是乎想到,UE用的方法应该不会低效吧,抄一个算了,也能学习学习,于是有段时间我就真的专心的去抄数学库了,不过恰好那段时间在学习3D数学,还是获益不少。然后是图片的解析我没有自己去折腾,而是采用了freeimage,这个库唯一的缺点就是大,其他的是还很方便全面。最后关于内存管理自己实现了一个简单的内存分配器,但是比较搞笑的是,这个管理器,我在我自己写的这些代码中并没有怎么使用,反而是我同学写的物理引擎用的多……但是后来出事了,在macos上这个内存管理器不能使用。

后来,我也曾今思考过将这个引擎移植到安卓或者ios上,有相当一段时间我都在做尝试,和一个懂苹果开发的同学搞了几天,解决了无数傻逼问题,最后在macos上跑了出来,但是却终究没有在osx上跑出来,安卓上,我也自己尝试了一下,感觉是还不如基于安卓重写来的快……

总之一句话,读书少而瞎想多

当初在做这个东西的时候,由于太年轻想的是将这个东西做成一个2D交互应用开发套件,最好的效果是能做做成一 个和Unity2D一样的东西。而当时看过的唯一一本书就是《Game Engine Architecture》,知道一个游戏引擎大概有哪些东西,但是这些东西具体怎么实现,则完全是一篇空白。尽管在后来的开发中,参考了cocos2d 和UE4,但是对原代码的解读都只是浅尝则止,没有深入的理解,往往是拿到一个概念,自己望文生义就乱实现。比如当时不知从什么地方了解到了多线程渲染这 个概念,于是想当然的设计了wip的多线程渲染系统,但是就是这个所谓的多线程系统导致现在整个渲染系统都像一只面目全非的怪兽。

WIP的Github

OSC镜像

【2D游戏引擎】WIP反思的更多相关文章

  1. 配置JDKAndroid 2D游戏引擎AndEngine

    配置JDKAndroid 2D游戏引擎AndEngine JDK全称为Java Development Kit(也即Java开发包),是用于支持Java 编程的基础.无论是什么编程,只要用到了Java ...

  2. Android 2D游戏引擎AndEngine配置环境

    Android 2D游戏引擎AndEngine配置环境 1.2  配置环境 在任何编程中,都需要一些软件或者硬件的支持.否则,没有硬件软件是不可能存在的,而想要编写对应语言的的程序,这需要对应语言库和 ...

  3. UWP简单示例(三):快速开发2D游戏引擎

    准备 IDE:VisualStudio 2015 Language:VB.NET/C# 图形API:Win2D MSDN教程:UWP游戏开发 游戏开发涉及哪些技术? 游戏开发是一门复杂的艺术,编码方面 ...

  4. 发布HTML5 2D游戏引擎YEngine2D

    关于YEngine2D YEngine2D是一个开源的.采用HTML5技术和Javscript语言创建的2D游戏框架,用来构建web二维游戏. GitHub地址 最新版本 v0.1.2 浏览器支持 C ...

  5. UWP简单示例(三):快速开发2D游戏引擎

    准备 IDE:Visual Studio 图形 API:Win2D MSDN 教程:UWP游戏开发 游戏开发涉及哪些技术? 游戏开发是一门复杂的艺术,编码方面你需要考虑图形.输入和网络 以及相对独立的 ...

  6. 【2D游戏引擎】那些年对游戏对象的思考

    WIP源代码: Github OSC镜像 对象系统以对象为中心,对象系统的最基本设计策略是基于组件的设计.对象系统将尽量避免使用继承方式来拓展游戏对象,恰当的使用Mix-in来来最属性做拓展,单个属性 ...

  7. 变态版大鱼吃小鱼-基于pixi.js 2D游戏引擎

    之前用CSS3画了一条

  8. 八款常见的Android游戏引擎

    原文地址:http://bbs.csdn.net/topics/380203732 1.Angle  Angle是一款专为Android平台设计的,敏捷且适合快速开发的2D游戏引擎,基于OpenGL  ...

  9. 2016年 最火的 15 款 HTML5 游戏引擎

    HTML5游戏从2014年Egret引擎开发的神经猫引爆朋友圈之后,就开始一发不可收拾,今年<传奇世界>更是突破流水2000万!从两年多的发展来看,游戏开发变得越来越复杂,需要制作各种炫丽 ...

随机推荐

  1. 100行代码搞定抖音短视频App,终于可以和美女合唱了。

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由视频咖 发表于云+社区专栏 本文作者,shengcui,腾讯云高级开发工程师,负责移动客户端开发 最近抖音最近又带了一波合唱的节奏,老 ...

  2. SIMD

    SIMD 概述 数据类型 静态方法:数学运算 静态方法:通道处理 静态方法:比较运算 静态方法:位运算 静态方法:数据类型转换 实例方法 实例:求平均值 概述 SIMD(发音/sim-dee/)是“S ...

  3. grunt-contrib-cssmin使用指南

    原文:http://riny.net/2014/grunt-cssmin/ grunt-contrib-cssmin v0.7.0 使用cssmin压缩css文件 Getting Started 这个 ...

  4. 实现 如 goole closure 类似功能模块加载函数

    看过goole  closure 的同学都知道  其中定义一个类名函数时候只要  inlude("")   想加载某个模块只要require("")就可以利用: ...

  5. [转].Net Core Web应用发布至IIS后报“An error occurred while starting the application”错误

    本文转自:http://www.cnblogs.com/TomGui/p/6438686.html An error occurred while starting the application. ...

  6. centos下不重装php——给PHP添加新扩展库

    装完php.发现需要一些新扩展库比如常见的mysqli之类的.在不重装php安装新扩展,以一个不常用的库xsl为例. 环境:centos6.8,php5.3.29 ,osx10.11.6 我的php相 ...

  7. ASP.NET Visual Studio2010 发布Web网站问题详解

    今天研究了一下如何发布web网站,之前总是没耐心,遇到点问题就没心情搞了,今天总算有点耐心搞明白了.其实遇到的问题还是挺多的,网上也没有太全的解释,所以结合自己还有别人的方法进行一下总结. 环境:Wi ...

  8. VS编译完成后自动复制到远程机器

    缘起 最近在调试网络通信,每次一有点小修改,都要将程序从开发机复制到测试机,不胜烦扰.既然我们程序猿,为什么要那么死板呢,能够用代码解决的问题,就不要用手去解决. 解决过程 复制 手工复制外有没有其他 ...

  9. IntelliJ IDEA 安装配置

    之前一直用的eclipse,以前公司的老大推荐过用这个,但是由于项目都比较赶,没及时学习. 后面这个公司的同时都用的idea,所以就换了 其实并没有那么难主要是刚刚切换时候快捷键不熟悉,打包什么的,有 ...

  10. Java 线程--继承java.lang.Thread类实现线程

    现实生活中的很多事情是同时进行的,Java中为了模拟这种状态,引入了线程机制.先来看线程的基本概念. 线程是指进程中的一个执行场景,也就是执行流程,进程和线程的区别: 1.每个进程是一个应用程序,都有 ...