cocos2d-X Physic 3D 教程-与地形交互

简介

在游戏中,户外场景通常使用地形来充当地面,而非扁平的地板,一些游戏要求能让地形参与到物理系统的演算当中,比方说一些越野车在地形上进行爬坡,这时候地形与物理的互动就非常的重要了,这一篇教程,我们将介绍一下如何将地形应用于cocos的物理系统。

读取导入高度场数据
首先我们必须要将地形高度场数据导入到物理系统中,cocos2d::Terrian提供了一个方法提供了高度场,数据并将其储存在一个std::vector中,这是一个尺寸为地形的高度图的宽 * 地形高度的高(当然为了谨慎起见,还是应该通过terrain->getTerrainSize()来获取)的数组,数组的指定位置index的数据为地形高度图中(index/width,index%width)位置的高度。
std::vector heidata =terrain->getHeightData();//读取高度场

创建高度场形状与刚体
读取了高度场数据后,我们就可以将其数据输入到物理系统中:
首先按照高度场数据定义形状
auto size = terrain->getTerrainSize();
rbDes.shape =Physics3DShape::createHeightfield(size.width, size.height, &heidata,1.0f, terrain->getMinHeight(), terrain->getMaxHeight(), true, false,true);
这里的形状和之前的创建方法有所不同,我们这里使用createHeightfield来创建高度场的形状,比较重要的是,我们需要指定地形的长和宽以及高度场数组的首地址(上一步得到的)。
根据形状,创建刚体:
auto rigidBody =Physics3DRigidBody::create(&rbDes);

加入组件
这样我们就已经创建好了,只要按照之前的教程所说,将其加入comopnent就可以了:
auto component = Physics3DComponent::create(rigidBody);
terrain->addComponent(component);

地形与其他刚体交互的例子
在上一步为止,我们已经将地形的高度场数据正确的加入到了物理系统里了,为了测试其他刚体与地形一起参与了物理运算,这里有一个小的例子——一大堆的小球“倾倒”在地形上,即在地形的正上方创建一系列球型刚体,并使其自由落体砸在地形上:
rbDes.mass = 1.f;
rbDes.shape = Physics3DShape::createSphere(0.5f);
float start_x = START_POS_X - ARRAY_SIZE_X/2 + 5.0f;
float start_y = START_POS_Y + 20.0f;
float start_z = START_POS_Z - ARRAY_SIZE_Z/2;

for (int k=0;k<ARRAY_SIZE_Y;k++)
{
for (int i=0;i<ARRAY_SIZE_X;i++)
{
for(int j = 0;j<ARRAY_SIZE_Z;j++)
{
float x = 1.0i + start_x;
float y = 5.0+1.0
k + start_y;
float z = 1.0*j + start_z;

auto sprite =PhysicsSprite3D::create(“Sprite3DTest/sphere.c3b”, &rbDes);
sprite->setTexture(“Sprite3DTest/plane.png”);
sprite->setCameraMask((unsigned short)CameraFlag::USER1);
sprite->setScale(1.0f /sprite->getContentSize().width);
sprite->setPosition3D(Vec3(x, y, z));
this->addChild(sprite);
sprite->syncNodeToPhysics();
sprite->setSyncFlag(Physics3DComponent::PhysicsSyncFlag::PHYSICS_TO_NODE);
}
}
}

这里用了三重的for循环,来建造了叠放在一起的行成一个长方体的若干小球,我们将小球指定好其质量后,它们将会在重力的效果下,向下方的地形下去,并会在地形的表面有若干反弹,当然我们为了增加趣味性,我们在小球与地形之间加了一个飞船加以阻碍,我们在这里不适用之前几篇教程的方式,而是直接读取把它网格三角列表抽取出来,然后适用它来构造形状,这样其形状是精准的和其网格相同,用于做更精密的碰撞:

std::vectortrianglesList=Bundle3D::getTrianglesList(“Sprite3DTest/boss.c3b”);rbDes.shape=Physics3DShape::createMesh(&trianglesList,(int)trianglesList.size() / 3);

:2: :2: :2: :2:

MarkMarkMarkMark

qq群:195391500

群:195391500 qq