P2中的形状(下)

p2中的形状(上)p2中的形状(下)中,我们掌握了p2中基本形状的创建,今天我们来学习一下p2形状的最后一课:通过Convex类,创建复杂的多边形形状。

创建三角形刚体

近日诸多网友问道这个问题,如果通过p2引擎创建三角形刚体。今天我们就来学习用来创建多边形(包括三角形)刚体的Convex类。

Convex是一个自定义多边形,可以根据它的数组属性vertices中保存的顶点,创建对应的形状,如下图所示:
Alt text

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个顶点的坐标,分别如下图所示:
Alt text
那么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直接创建刚体,就会出现问题。
Alt text

因为随手绘制的形状,可能会出现凹多边形,而Convex类是不支持凹多变形的碰撞检测的,此时创建的多边形会出现以下类似的错误。
Alt text

所以这个时候就要用到新的只是点: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 = [];
    }

创建好的刚体,可以完美的实现碰撞检测,如下图所示。
Alt text

点击下载源文件,编译代码后,试着在舞台中使用鼠标绘制任意形状,松开鼠标后,会自动创建对应形状的刚体。

联系作者

公众号:拉小登 | 微博:拉登Dony | B站:拉小登Excel

4 Replies to “P2中的形状(下)”

  1. 想请教一个问题。想用P2做一个无重力无摩擦力的物理世界。给物体一个初始力之后,可以在碰撞范围内一直运动下去。我试着设置了初始的restitution为1,friction为0.但是在物体有质量的情况下还是会慢慢停下来。请问事我哪里没有设置对,还是什么地方有疏漏?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注