创建半圆形刚体
今天网友【纯洁的坏蛋】提问,如何在Box2D中创建一个半圆形的刚体。回想一下,我曾经在Box2D工具类(AS3版本)LDEasyBox2D中,创建了一个静态方法,createSemiCircle(),可以简单的创建一个半圆形形状。
LDEasyBox2D类库在github仓库上的地址:
https://github.com/ladeng6666/LDEasyBox2D
刚才花了几分钟时间,把createSemiCircle()方法,转换成了Egret + p2环境下实现方案。
首先,我们来看一下详细的代码:
private createSemiCircle(w:number,h:number): number[][] {
var arcSimulateAnglePrecise: number = 10*Math.PI/180;
w /= this.factor;
h /= this.factor;
var r:number = (h*h+w*w/4)/h/2;
var angleSize:number = Math.acos((r-h)/r)*2;
if(angleSize<arcSimulateAnglePrecise) throw Error("the angle of semicircle is too small");
var verticesList:number[][] = new Array();
var tempVertex: number[] = new Array();
var verticesCount:number = Math.floor(Math.PI*2/arcSimulateAnglePrecise * angleSize/Math.PI/2);
for (var i:number = 0; i < verticesCount; i++)
{
tempVertex= new Array(
r*Math.cos(arcSimulateAnglePrecise*i + (Math.PI-angleSize)/2),
r*Math.sin(arcSimulateAnglePrecise*i + (Math.PI-angleSize)/2) -r+h
);
verticesList.push(tempVertex);
}
tempVertex= new Array(
r*Math.cos(angleSize + (Math.PI-angleSize)/2),
r*Math.sin(angleSize + (Math.PI-angleSize)/2) -r+h
);
verticesList.push(tempVertex);
return verticesList;
}
createSemiCircle()函数的用方法大概是这样的:
- 提供半圆形的宽w和高h
- 以w和h为参数,调用createSemiCircle()函数,获取半圆形的顶点数组vertices。
- 使用body类的fromPolygon()函数,创建对应形状的刚体。
关于fromPolygon()函数的用法,请参考教程:p2中的形状(下)。
点击下载源文件并编译成功后,点击舞台任意位置,可以创建宽和高随机的半圆形,如下图所示:
原理说明
在p2中,除了标准圆,我们无法直接绘制完美的圆弧。当需要的时候,只能通过多边形Convex形状,创建一个标准等分的多边形来模拟。例如下图中,用12等边的多边形模拟的圆形。
这时,每个边与圆心形成的夹角,即为代码中的arcSimulateAnglePrecise变量。
那么假设现在我们要创建一个宽为w,高为h的半圆形,那么代码中其他的临时变量,如下图所示:
然后,绘制半圆形的大致步骤如下:
- 当angleSize < arcSimulateAnglePrecise时,不绘制刚体形状。
- 按照勾股定理,我们可以列出下面的公式:
解方程可以得到圆形的半径r为:
var r:number = (h*h+w*w/4)/h/2;
- 根据angleSize 和 arcSimulateAnglePrecise变量,计算出半圆形的顶点个数verticesCount。
- 循环遍历,计算每一个顶点的坐标。
- 将这些坐标保存在verticesList数组中。
最后,通过body类的fromPolygon()函数,和createSemiCircle()返回的顶点数组,就可以轻松的创建出半圆形状的刚体啦。
联系作者
多谢 多谢