大佬教程收集整理的这篇文章主要介绍了cocos2dx实现自定义2D地形,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
先来看看效果:
对于2D地形的生成,可以采用2种方法,
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()); //读取顶点个数
memcpy(&_points[0],data.getBytes()+4,data.getSize()-4); //读取顶点数据
这里_points是std::vector<Vec2>_points;
vector的数据是连续的,而且Vec2又占8个字节,又不需要特殊的构造。
下一步就是将顶点数据转换成三角形顶点
对于土地部分
只要保证顶部地形的走势就可以,底部要做的就是一直拖到屏幕最下方,
所以根据上面标有数字的图片,按照数字顺序添加顶点就可以了。
而对于表面(草地)部分
纹理的处理
纹理采用的是GL_REPEAT,对于地形的显示至关重要。
那么纹理坐标应该怎么生成呢?
土地可以根据(坐标/图像的尺寸)得到。
表面水平方向/图像的宽带,竖直方向不能根据坐标,因为纹理是重复的,
只要将上顶点设为0.f,下顶点设为1.0f,就可以,纹理坐标Y坐标与opengl坐标系是相反的。
顶点坐标纹理都已准备好,下面就是如何绘制了.
Shader+绘制函数就可以搞定了,
继承Node,重载draw函数
定义一个Customcatommand,目的调用自己的绘制方法,
我们并没有使用glVertexPointer,glTexCoordPointer,因为可以利用cocos2dx的shader设置顶点属性
getGLProgramState()->setVertexAttribPointer,
可以这样提供给shader顶点坐标,前提顶点着色器要有attributevec4a_position
getGLProgramState()->setVertexAttribPointer("a_position",GL_FLOAT,138); font-size:9.5pt; font-family:新宋体">GL_falSE,sizeof(Vec2),&_triangles[0]);
同理纹理坐标
"a_texCoord",&_texCoords[0])
可以参照tests的ShaderTests
到此我们已经知道地形绘制的方法,具体怎么实现呢?
组织方式 Terrain类管理地形的表面和土地
TerrainSurface类和TerrainBottom类分别显示地形的表面和土地
两者继承TerrainSprite类,TerrainSprite类显示自定义网格,
考虑一下Surface和Bottom不同之处:纹理,三角形数据,shader
仅仅几个参数不同,所以可以合并到TerrainSprite.
先来分析Terrain,载入地形数据,初始化表面和土地
初始化代码:
然后TerrainSprite,根据顶点数据构造三角顶点和纹理顶点,初始化shader,并绘制,头文件就不用看了,
由于三角形的处理不同所以提供了一个纯虚函数,让子类实现。
重点是这句
node->init(points,"glsl/terrain_surface.vert",21); font-size:10.5pt; font-family:新宋体">"glsl/terrain_surface.frag");
纹理,shader,其实create还可以提供一个Texture2D*的参数以便得到不同的纹理。
initTriangles,在文章前面已经提到过,51); font-family:Arial; font-size:14px; line-height:26px; margin-bottom:0pt; margin-top:0pt"> TerrainBottom类似,具体请在文章最后下载源码查看。
Shader的编写
顶点着色器
片元着色器
可见自定义数据,可以通过shader轻松更改显示特效,同时还可以添加物理特性.
以上是大佬教程为你收集整理的cocos2dx实现自定义2D地形全部内容,希望文章能够帮你解决cocos2dx实现自定义2D地形所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。