Nape柔体教程(5)

作者: ladeng6666 分类: Nape 发布时间: 2013-05-28 22:30 阅读: 3,126

还记得我们学习的柔体创建的步骤吗?

一、用多个segment刚体组成柔体形状的轮廓,并用PivotJoint链接起来。

  1. 柔体的轮廓完全由segment刚体的形状组成,而非PivotJoint关节。
  2. 两个相邻segmentBody刚体之间用两个PivotJoint关节连接。

多边形柔体的创建过程基本上是一样的,不同之处在于步骤1.a,segment刚体的计算方法。

圆形是一个标准的正圆,它的轮廓通过三角函数和内外径可以轻松计算出来,然后分割成多个顶点,组成一个个小的segment刚体。但是多边形大多是不规则的形状,没有一个万能的公式来计算出这些形状的轮廓,所以我们要在这个问题上绕些弯子。

二、在刚体segment刚体的垂直方向施加作用力,把轮廓支撑起来。

  1. 获取刚体segment刚体外侧的边。
  2. 获取作用力方向。

这一点,我们在第4节柔体教程里也学习过了,没有太大的差异。不过第4节的作用力我是通过一个参数定义好之后(比如10),直接调用applyImpulse施加的,这一节我要教你另外一个方法。

首先我们快速浏览一下多边形柔体的创建方法。

  1. 获取多边形轮廓内外边界顶点,并计算出内外边界
  2. 针对内外边界进行等分
  3. 用等分边界生成的顶点创建segment刚体

softbody5-1

下面我们来仔细看一下具体每个步骤的实现过程。

获取内外边界顶点

对应多边形顶点的处理,Nape为我准备了一个专门的类GeomPoly(我在用GeomPoly创建多边形刚体中曾经讲过),我们可以将存储了顶点的Array<Vec2>, flash.Vector<Vec2>, Vec2List等类型传入到GeomPoly的构造函数中,实例化一个GeomPoly对象,然后调用相应的函数。

多边形的外边界顶点是很容易获取的,Polygon提供的静态方法box()、rect()和regular()方法都可以返回一个包含了多边形顶点的Vec2List对象,我们可以传递给GeometryPoly进行实例化。

outPoly = new GeomPoly( Polygon.box());

softbody5-2

那么怎么获取轮廓的内边界呢?同样还是求助于GeomPloy类了。GeomPoly有一个inflate()函数,用于对存储的多边形进行缩放。还记得Box2D缩放教程吗?inflate方法相对把多边形缩放方法单独放到了一个函数中。

inflate()的参数表示多边形缩放的尺寸,以像素为单位。整数表示多边形放大,负数表示缩小。然后将缩放后的多边形顶点存储到一个GeomPoly对象中返回。下面的代码将outPoly缩小10个像素并返回到innerPoly中去。

innerPoly = outPoly.inflate(-10);

softbody5-3

 

等分内外边界

等分边界之前,要知道等分后的segmentBody的长度,这一点并不难,我可以预先定义好保存到一个变量segmentLength中。

然后用要等分的边界长度outEdge.length除以segmentLength,计算出等分后segment的数量segmentNum,再循环遍历计算每个片段的顶点。

用等分边界生成的顶点创建segment

计算出每个顶点之后就简单多了,和圆形柔体一样,把这些顶点按照指定的顺序组合成一个刚体segment,然后逐个用PivotJoint关节连接起来,形成多边形柔体。

讲了这么多,估计你已经看烦了,还是先看看完成后的效果吧。在下面的示例中,点击右上角的GasON按钮,可以添加或消除柔体的支撑力。

Sorry, either Adobe flash is not installed or you do not have it enabled

代码如下:

第21行:每个软体由多个简单的刚体组成,这些刚体由一个Compound对象统一管理,你可以把他想象成 一个包含多个Sprite的Sprite容器。所以,用来保存柔体的数组是 Vector.<Compound>类型的。
第22行:segmentLength定义了每个刚体片段的长度
第24行:isGasOn表示是否对柔体施加由内向外的支撑力。
第26~42行:定义好全局变量之后,因为示例继承了AbstractNapeTest类,所以代Nape世界创建好之后,会自动调用 onNapeWorldReady()函数,我们在这个函数里创两个软体,一个矩形、另一个是5边形。然后调用 addJuggleButton()函数添加一个开关按钮。
第44~128行:
这个createSoftBody函数是本节的重点。调用createSoftBody后会创建一个柔体对象,并返回,在返回
之前,我把他存储到45行定义的softBody对象中。
我说过需要把多边形的边分解成多个片段,我们把这些片段保存到segmentList数组中。
实际上,每条边都是要根据前面定义的segmentLength进行等分的,等分后的数量保存到segmentNum变量
中。
第51~53行:分别用outPoly和innerPoly保存了多边形的内外轮廓,这里用到了前面介绍的
GeomPoly.inflate()方法,来获取内边界innerPoly。后面的代码会将内外边界的顶点分别保存到
innerPoints和outPoints数组中。
第55行:多边形分割成多个片段后,将这些片段的最外面的边存储到outSegmentEdgeList中,稍后计算
支撑力方向和多边形面积时会用到。
第57行:记录多边形的第一个顶点,后面我们会逐一遍历多边形的每个顶点,获取每条边进行分割。
第59~94行:这里的do while循环用来遍历每一条边,并对每条边进行分割,就像上图中的第2部。
第60~63行:首先调用outPoly.current()函数记录多边形的起始顶点,然后执行skipForward(1),将顶
点的索引移至下一个顶点,并保存到outNext变量中。然后用outNext减去outCurrent,我们就得到了多
边形的第一条外边界。
第65~68行:用上面同样的方法,计算多边形的内边界。
第70行:计算刚体片段的数量segmentNum。
第72~89行:这里的这个for循环,是循环将当前索引到的多边形边界,分割成多个小的片段,并保存到
segmentList中去。
第73~76行:计算分割后的刚体片段的4个顶点。
第78~82行:通过上一步计算的顶点创建刚体片段。
第84~85行:保存刚体片段的内外顶点,稍后创建PivotJoint关节时会用到。
第86行:将刚体片段保存到segmentList中去。
第88行:将刚体片段的最外面的边保存到outSegmentEdgeList中,稍后计算支撑力方向和面积时用到.
第90~91行:删除临时变量,节约内存
第99~119行:循环遍历segmentList里的刚体,用PivotJoint将它们连接起来。
第120~122行:调整每个刚体的坐标至柔体的坐标位置,因为创建初始,是基于坐标原点(0,0)的
第123~124行:保存柔体的面积,以及所有外边缘的引用,稍后就算支撑力时用到
第129~142行:循环遍历每个柔体,对每个柔体内的刚体施加由内向外的作用力。
第133行:第一层for循环遍历softBodyList中的每个柔体。
第134行:柔体变形后,他的面积会变小,我们可以理解成对气球的挤压,我们挤压的越用力,内部气体对气球的支撑力也越大。所以这里的pressure是用开始我们在第123行保存的面积,减去用getArea实时计算出来的面积,所谓作用力。
第136~139行:遍历第124行我们保存的每个外边缘,通过Edge.worldNormal()方法获取垂直该边缘的方向作为作用力的方法,然后用mul()方法乘以刚才计算出来的pressure,施加给刚体片段

第148~160行:用外边缘的顶点新建一个Polygon,然后用Polygon.area()实时计算柔体的面积

点击下面源代码

 

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

一条评论
  • hyieq

    2014 年 11 月 3 日 下午 5:11

    一开始以为很复杂很复杂,拉登讲的好到位哈哈

发表评论

电子邮件地址不会被公开。 必填项已用*标注