在cocos2dX 3.6 中,我们为3D部分增加了一个Terrain——地形类,用以模拟现实生活中诸如草地、荒漠、丘陵地带等自然景观,能够丰富游戏场景。这篇教程将会向大家简单介绍一下Terrain类所涵盖的功能,以及基础的用法。
Terrain:
从编程的角度来说,地形就是通过载入一张高度图和若干张细节纹理,从而在场景中绘制若干高低不平的几何体,用以在游戏场景中模拟自然中的沙漠,草原等景象的一种手段。从地形的资源构成角度来说,包含了下面几个元素:
高度图:
高度图是Terrain类的核心,高度图从性质上来说是简单的一张图片,但是图片中的每一个像素的颜色值并不被当做颜色,而是直接被视为一个高度的值。Terrain类就通过高度图所给的高度信息,加以适当的缩放,而构建出整个地形的Mesh结构。
细节图:
如果说高度确定了整个Terrain的几何形状,那么细节图则确定了Terrain的外观。通过将细节图贴在Terrain上,可以制造非常好的表现效果。由于Terrain在世界坐标系下,尺寸可能会非常的大,如果单纯将细节图平铺在Terrain上,表现会非常模糊,效果很不好,因此Terrain通过制定细节图的平铺尺寸来解决此问题。
Alpha贴图:
Alpha贴图用于控制Terrain上的细节图是在Terrain上何处以及如何绘制的。Alpha贴图从本质而言,也是一张图片,但是它将图片中每个像素中的Red,Green,Blue以及Alpha通道对应四张细节图的Terrain某个位置上,每一张细节图颜色比例是多少。通过这种方式,我们就可以在Terrain上同时出现诸如沙丘,石板路,草地等纹理,使得Terrain的外观不再那么单调,同时Alpha贴图的结构简单,可以使用外部的编辑器就能直接修改。
Terrain入门
下面我们从两个例子出发来看看,如何在Cocos2Dx中使用Terrain。这里分为两个部分,第一部分介绍如何创建一个简单的地形,第二部分介绍如何在Terrain上放置一个角色,并通过触摸(点击)使角色在Terrain中漫游。
创建地形
需要创建地形需要分类两步,第一步是构造出Terrain所需参数的结构体——Terrain::TerrainData,第二步,通过该TerrainData来创造地形。
首先,我们需要构建出地形需要的所有细节图:
细节图以Terrain::DetailMap结构体的形式存储,其构造函数有两个参数,第一个是细节图的路径,第二个是细节图的在地形上的平铺尺寸,第二个参数有默认值,是可选的。
Terrain::DetailMap r(“TerrainTest/dirt.dds”);
Terrain::DetailMap g(“TerrainTest/Grass2.dds”);
Terrain::DetailMap b(“TerrainTest/road.dds”);
Terrain::DetailMap a(“TerrainTest/GreenSkin.jpg”);
然后,我们使用细节图构造出Terrain::TerrainData:
Terrain::TerrainData 的构造函数有若干种形式以满足用户不同的构造地形的需求,在这里我们只给出最常用的一种,构造函数的第一个参数为高度图的路径,第二个参数为Alpha贴图的路径,接下来的四个参数为之前所构造的四个DetailMap结构体。
Terrain::TerrainData data(“TerrainTest/heightmap16.jpg”,“TerrainTest/alphamap.png”,
r,g,b,a);
最后,将构造出来的TerrainData传给Terrain::create即可创建出地形了。
_terrain = Terrain::create(data,Terrain::CrackFixedType::SKIRT);
Terrain::create的第二个参数为地形LOD裂缝的缝补方法,LOD简单来讲就是通过将远处的地形块的Mesh加以简化,从而在不影响视觉效果的情况下,提高性能的方法。但是如果临近的两个地形块的LOD不同时,其边缘可能会出现裂缝,为了游戏效果的美观,我们需要对裂缝进行填补。Terrain提供两种方式对裂缝进行填补,分别是裙边以及补边的方法,在这里我们使用裙边法来对裂缝进行填补。
地形的效果如图所示:

创建角色在地形上行走
首先我们先创建一个角色的Sprite3D,让其播放动画并将其加入场景里:
_player = Sprite3D::create(“Sprite3DTest/girl.c3b”);
_player->setCameraMask(2);
_player->setScale(0.08);
_player->setPositionY(_terrain->getHeight(_player->getPositionX(),_player->getPositionZ())+PLAYER_HEIGHT);
auto animation = Animation3D::create(“Sprite3DTest/girl.c3b”,“Take 001”);
if (animation)
{
auto animate = Animate3D::create(animation);
_player->runAction(RepeatForever::create(animate));
}
接着使相机跟随角色的位置移动:
_camera->setPosition3D(_player->getPosition3D()+camera_offset);
_camera->setRotation3D(Vec3(-45,0,0));


