我最初认为问题可能来自两个相邻线段之间的坡度变化,但由于在多边形的平坦表面上仍然有凹凸,我认为问题在于击中多边形的角。
不知道能不能设置两组多边形,互相重叠?只需使用相同的插值计算并生成第二组多边形,如下图所示:您已经构建了红色的多边形集,并通过将绿色多边形的左顶点设置在红色多边形的中间来添加绿色集,及其右顶点在下一个红色多边形的中间。
![图表][1]
这应该适用于凹曲线,并且......无论如何你应该飞越凸曲线。
如果这不起作用,请尝试设置大量多边形来构建斜坡。使用圆半径的十分之一作为多边形的宽度,甚至更小。这应该会减少您的坡度不连续性。
-- 编辑
在 Box2D.js 的第 5082 行(至少在 this 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
};