先来看看效果:
1.使用建模软件将2D的地形模型构建好直接使用Sprite3D导入
优点:不需要太多程序控制,只是简单的导入
缺点:需要建模,而且还要转换成2D坐标,很难使用chipmunk加入物理特性
2.根据自定义数据使用顶点数据和shader。
下面来讲解如何实现,之后分析优缺点。
推荐一篇博客
如何制作一个类似TinyWings的游戏Cocos2d-x2.1.4
如果你看懂了上面的博客,那么就跟容易理解笔者讲解的。
首先准备,图片资源
草地(地形表面) 土地(地形底部)
地形数据,其实是由许多点连成线组成的,如图
只要获取这些点就可以得到一个比较平滑的地形,如果点的间隔比较大,得到的地形就没有那么平滑,所以两个点的水平距离要根据需要设置。
由于主要讲解如何根据点生成地形,这里就不讲解如何生成这么多点,有兴趣的同学可以加
QQ:842723654,一起讨论。
有了数据,那么应该如何生成地形呢?
我们都知道大多数3D模型是由许多点组成的(有些模型也包含曲线),这些点就组成了许多三角形,
这些三角形就组成了一个模型,给这个模型赋予贴图,就得到了一个完整的模型。
同样利用这个道理,我们可以自己构造一个2D模型。
对于上面由线段组成的曲线,如果将每一个点复制后向下平移一定的距离,就能得到
许多矩形(实际就多了一倍的顶点,目前还是点),现在就要把这些矩形拆分成三角形,
每个矩形沿对角线切割,就得到了三角形。
让我们想想opengl绘制三角形的方法,
glBegin(GL_TRIANGLES);.....glEnd();这种方法又慢又费资源。
glBegin(GL_TRIANGLE_STRIP);.....glEnd();这种方法比刚才的快了一点
glDrawArrays(GL_TRIANGLE_STRIP,);这种一次绘制的就是我们想要的,
其实cocos2dx也是利用glDrawArrays来减少绘制次数的,尤其是对于粒子,一次性
传入所有粒子的顶点,一次性绘制,岂能不快。
这里也提一下,假如提供了1,2,3,4,5,6,6个顶点:
GL_TRIANGLES,每三个顶点构成一个三角形,(1,3),(4,6),绘制2个三角形
GL_TRIANGLE_STRIP,前面的两个顶点与当前顶点构成一个三角形,
(1,(2,4),(3,5),绘制4个三角形
可见如果要节约资源,采用GL_TRIANGLE_STRIP是个不错的选择。
关于地形顶点数据的存储,笔者采用文件存储,前4个字节,表示顶点的个数,
以后每8个字节表示一个顶点,因为Vec2就占8个字节,正好可以读入。
如下,载入数据:
autodata=FileUtils::getInstance()->getDataFromFile(fileName);
CC_BREAK_IF(data.isNull());
intnumPoint=*((int*)data.getBytes()); //读取顶点个数
_points.resize(numPoint);
memcpy(&_points[0],data.getBytes()+4,data.getSize()-4); //读取顶点数据
这里_points是std::vector<Vec2>_points;
vector的数据是连续的,而且Vec2又占8个字节,又不需要特殊的构造。
下一步就是将顶点数据转换成三角形顶点
对于土地部分
- boolTerrainBottom::initTriangle(std::vector<Vec2>&points)
- {
- //triangles
- Vec2pt(0.f,0.f);
- for(std::size_ti=0;i<points.size();++i)
- pt.x=points[i].x;
- _triangles.push_back(pt);//先下方顶点
- _triangles.push_back(points[i]);//再上方顶点
- }
- _bUserTexCoord=false;//是否使用自定义纹理坐标
- returntrue;
- }
只要保证顶部地形的走势就可以,底部要做的就是一直拖到屏幕最下方,
而对于表面(草地)部分
实际上就是给土地镶嵌一层花边,如图中的黑色粗线
只要将每个顶点的Y坐标上下平移一小段距离,得到图中的橘色多边形就可以了