我首先认为问题可能来自两个相邻段之间的斜率变化,但由于在多边形的平面上仍然有凹凸,我认为问题在于击中多边形的角落。
我不知道你是否可以设置两组多边形,相互重叠?只需使用相同的插值计算并生成第二组多边形,如下图所示:您已经构建了红色的多边形集,并通过将绿色多边形的左顶点设置在红色多边形的中间来添加绿色集,及其在下一个红色多边形中间的右顶点。
![图表][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
};