21

我正在尝试像在 javascript 中那样做一个 Tiny Wings。

我第一次看到使用 Box2D 的技术,我使用的是closure-web 版本(因为内存泄漏修复)。
简而言之,我将曲线分解为多边形,如下所示:

在此处输入图像描述

我还尝试使用 Chipmunk-js,并使用分段形状来模拟我的地面:

在此处输入图像描述

在这两种情况下,当一个圆圈滚动时,我在多边形或线段之间的公共点处都遇到了一些“崩溃”或“颠簸”。

我向 Chipmunk 询问了这个问题,作者说他为该段实现了一个半径属性以减少这种行为。我试过了,它确实成功了,但它并不完美。我仍然有一些颠簸(我必须设置为 30px 的半径才能获得积极的效果)。

“凹凸”附加在两个多边形之间的共享点处:

撞虫

正如illandril向我建议的那样,使用边缘技术 (他只测试了多边形-多边形接触)来避免圆在边缘上崩溃:

边坡修边技术

还尝试按照 Luc的建议添加项目符号选项,但似乎没有任何改变。

这里是问题的演示
您可以尝试更改要检查的值:

  • 项目符号选项
  • 边缘尺寸
  • 迭代次数
  • 物理学

(仅在最新的开发 Chrome 上测试过)
请耐心等待(或更改水平重力),您会明白我的意思。
这里是感兴趣的回购

4

3 回答 3

2

最好的解决方案是带有幽灵顶点的边缘形状,但如果您使用的版本/端口中不可用,那么下一个最好的事情就是您的问题中称为“边缘”的图表,但是将多边形进一步扩展到地下浅坡,就像在这个线程中: http: //www.box2d.org/forum/viewtopic.php? f=8&t=7917

于 2013-02-25T15:25:06.763 回答
1

我首先认为问题可能来自两个相邻段之间的斜率变化,但由于在多边形的平面上仍然有凹凸,我认为问题在于击中多边形的角落。

我不知道你是否可以设置两组多边形,相互重叠?只需使用相同的插值计算并生成第二组多边形,如下图所示:您已经构建了红色的多边形集,并通过将绿色多边形的左顶点设置在红色多边形的中间来添加绿色集,及其在下一个红色多边形中间的右顶点。

![图表][1]

这应该适用于凹曲线,并且......无论如何,你应该飞越凸曲线。

如果这不起作用,请尝试设置大量多边形来构建斜坡。使用圆半径的十分之一作为多边形的宽度,甚至更小。这应该会减少您的坡度不连续性。

- 编辑

在 Box2D.js 的第 5082 行(至少在这个 repo中)你有 PreSolve(contact,manifold) 函数,你可以覆盖它来检查流形(碰撞多边形时雪球的冲击方向)是否正确。

为此,您需要恢复流形矢量并将其与曲线的法线进行比较。它应该看起来像这样(也许不完全是):

Box2D.Dynamics.b2ContactListener.prototype.PreSolve = function (contact, oldManifold) {
    // contact instanceof Box2D.Dynamics.Contacts.b2Contact == true
    var localManifold, worldManifold, xA, xB, man_vect, curve_vect, normal_vect, angle;
    localManifold = contact.GetManifold();

    if(localManifold.m_pointCount == 0)
        return; // or raise an exception

    worldManifold = new Box2D.Collision.b2WorldManifold();
    contact.GetWorldManifold( worldManifold );

    // deduce the impulse direction from the manifold points
    man_vect = worldManifold.m_normal.Copy();

    // we need two points close to & surrounding the collision to compute the normal vector
    // not sure this is the right order of magnitude
    xA = worldManifold.m_points[0].x - 0.1;
    xB = worldManifold.m_points[0].x + 0.1;

    man_vect.Normalize();

    // now we have the abscissas let's get the ordinate of these points on the curve
    // the subtraction of these two points will give us a vector parallel to the curve

    var SmoothConfig;

    SmoothConfig = {
        params: {
            method: 'cubic',
            clip: 'mirror',
            cubicTension: 0,
            deepValidation: false
        },
        options: {
            averageLineLength: .5
        }
    }
    // get the points, smooth and smooth config stuff here
    smooth = Smooth(global_points,SmoothConfig);

    curve_vect = new Box2D.Common.Math.b2Vec2(xB, smooth(xB)[1]);
    curve_vect.Subtract(new Box2D.Common.Math.b2Vec2(xA, smooth(xA)[1]));

    // now turn it to have a normal vector, turned upwards
    normal_vect = new Box2D.Common.Math.b2Vec2(-curve_vect.y, curve_vect.x);
    if(normal_vect.y > 0)
        normal_vect.NegativeSelf();
    normal_vect.Normalize();
    worldManifold.m_normal = normal_vect.Copy();

    // and finally compute the angle between the two vectors
    angle = Box2D.Common.Math.b2Math.Dot(man_vect, normal_vect);

    $('#angle').text("" + Math.round(Math.acos(angle)*36000/Math.PI)/100 + "°");
    // here try to  raise an exception if the angle is too big (maybe after a few ms)
    // with different thresholds on the angle value to see if the bumps correspond
    // to a manifold that's not normal enough to your curve 
};
于 2012-05-20T15:36:30.897 回答
0

我想说这个问题已经在 Box2D 2.2.0 中得到解决,请参阅它的手册,第 4.5 节“边缘形状”

问题是它是 2.2.0 版本的一个功能,以及链形的东西,box2dweb 实际上是从 2.2.1a 移植的——不知道 box2dweb-closure。

我通过修改 Box2D.Collision.b2Collision.CollidePolygonAndCircle 进行的任何尝试都导致了不稳定的行为。至少有一部分时间(例如,球在随机方向上碰撞,但仅在它缓慢滚动时)。

于 2012-06-24T18:31:44.730 回答