P2中的形状(下)
在p2中的形状(上)和p2中的形状(下)中,我们掌握了p2中基本形状的创建,今天我们来学习一下p2形状的最后一课:通过Convex类,创建复杂的多边形形状。
创建三角形刚体
近日诸多网友问道这个问题,如果通过p2引擎创建三角形刚体。今天我们就来学习用来创建多边形(包括三角形)刚体的Convex类。
Convex是一个自定义多边形,可以根据它的数组属性vertices中保存的顶点,创建对应的形状,如下图所示:
Convex形状的构造函数如下:
function Convex(
options?: {
vertices: number[],
axes:number[]
}
)
参数说明:
- vertices:保存了顶点坐标的数组。它应该是一个二维数组,每个元素应该由x和y坐标组成的一维数组,例如:vertices=[[-1,-1],[1,-1],[1,1],[-1,-1]]
- axis:表示多边形各个边的垂直法向量,同样是一个二维数组,且其长度应与vertices一直。
这个参数通常可以保持缺省,convex类会根据vertices中的顶点,自动计算得出。
明白了convex多边形的结构之后,只要拥有了形状的顶点,我们就可以创建出任意性在的刚体。以简单的三角形为例,假设三角形3个顶点的坐标,分别如下图所示:
那么p2中对应创建三角形刚体的代码如下:
private createTriangle(): void {
var vertices:number[][] =
[
[0,-80/this.factor],
[40/this.factor, 30/this.factor],
[-40/this.factor,30/this.factor]
];
var triangleShape: p2.Convex = new p2.Convex({vertices:vertices});
var body: p2.Body = new p2.Body({ mass: 1,position:[100/this.factor,100/this.factor] });
body.addShape(triangleShape);
this.world.addBody(body);
}
需要说明的是,虽然p2中的convex支持多边形Convex,但以下两种情况是无效的,会形状创建失败,以及不可预知错误,我们应当有意的去避免。
- convex形状中有中空的洞洞
- convex的顶点、边之间有交叉
运行时绘制刚体
使用Convex创建简单的三角形没有什么大问题,但是如果要做一个类似《叫醒盒子》的游戏,使用Convex直接创建刚体,就会出现问题。
因为随手绘制的形状,可能会出现凹多边形,而Convex类是不支持凹多变形的碰撞检测的,此时创建的多边形会出现以下类似的错误。
所以这个时候就要用到新的只是点:body.fromPolygon()函数。
fromPolygon()函数会根据参数中的顶点数组,对形状自定进行判断和分解,将多边形分解成多个小的形状,并保存到刚体body中。
fromPolygon()函数的结构很简单:
function fromPolygon(vertices:number[][]):p2.Body{ }
函数只有一个vertices,表示多边形的顶点。fromPolygon会自动创建刚体,并将分解后的形状保存在里面,因此我就不用单独的去创建刚体。具体使用方法,如以下代码所示:
private createConvexBody(): void {
/* 错误的做法,使用Convex形状,创建多边形.
var triangleShape: p2.Convex = new p2.Convex({vertices:this.points});
var body: p2.Body = new p2.Body({ mass: 1, position:[100/this.factor,100/this.factor] });
body.addShape(triangleShape);
*/
//正确的做法,使用fromPolygon()函数,来创建刚体
var body: p2.Body = new p2.Body({ mass: 1 });
body.fromPolygon(this.points, {optimalDecomp:false});
this.world.addBody(body);
this.points = [];
}
创建好的刚体,可以完美的实现碰撞检测,如下图所示。
点击下载源文件,编译代码后,试着在舞台中使用鼠标绘制任意形状,松开鼠标后,会自动创建对应形状的刚体。
联系作者
想请教一个问题。想用P2做一个无重力无摩擦力的物理世界。给物体一个初始力之后,可以在碰撞范围内一直运动下去。我试着设置了初始的restitution为1,friction为0.但是在物体有质量的情况下还是会慢慢停下来。请问事我哪里没有设置对,还是什么地方有疏漏?
Convex形状的坐标系错了,x轴右为正,y轴上为正,顶点逆时针填入数组。
请问这个问题解决了吗?
大神牛批,正在研究这个