我正在进行服务器端物理实验,用户通过套接字控制对象。当用户将对象移出世界的边界时,我遇到了问题。
我正在通过npm
安装Box2Dj。
我创建了世界500x500,然后将以下监听器附加到它:
var boundaryListener = new b2d.b2BoundaryListener();
boundaryListener.Violation = function (body) {
//we will move this body to the opposite side
var position = body.GetWorldCenter();
//snap to opposite side
if (position.x < 0) {
position.x = worldAABB.upperBound.x + position.x;
}
if (position.y < 0) {
position.y = worldAABB.upperBound.y + position.y;
}
if (position.x > worldAABB.upperBound.x) {
position.x -= worldAABB.upperBound.x;
}
if (position.y > worldAABB.upperBound.y) {
position.y -= worldAABB.upperBound.y;
}
body.m_flags = body.m_flags & (~b2d.b2Body.e_frozenFlag); //does nothing :(
}
this.world.SetBoundaryListener(boundaryListener);
worldAABB
是世界用作边界的b2AABB。
问题是我注意到当边界监听器被触发时,标志被设置为22,即allowSleep,frozen和island标志。当b2Body通过世界边界时,它似乎被冻结了。最后一行是试图通过弄乱内部标志来解冻身体,但我有一种明显的感觉,这是错误的做法。
如何解冻身体?没有任何功能可以清除我可以看到的冻结标志(javascript超过10,000行,所以我老实说没有阅读整个事物)并且放置一些物体作为墙似乎没有效果(用户的物体正好通过它们)。
我的墙壁是这样创建的:
//create walls
var wallShape = new b2d.b2PolygonDef();
wallShape.SetAsBox(500, 10);
wallShape.density = 0.0;
wallShape.friction = 0.3;
var bodyDef = new b2d.b2BodyDef();
bodyDef.position.Set(250, 20);
var north = this.world.CreateBody(bodyDef);
north.CreateShape(wallShape);
bodyDef = new b2d.b2BodyDef();
bodyDef.position.Set(250, 499);
var south = this.world.CreateBody(bodyDef);
south.CreateShape(wallShape);
bodyDef = new b2d.b2BodyDef();
bodyDef.position.Set(499,250);
bodyDef.angle = Math.PI / 2;
var east = this.world.CreateBody(bodyDef);
east.CreateShape(wallShape);
bodyDef = new b2d.b2BodyDef();
bodyDef.position.Set(1, 250);
bodyDef.angle = Math.PI / 2;
var west = this.world.CreateBody(bodyDef);
west.CreateShape(wallShape);
有没有人对如何解决这个问题有任何见解?除了网站指向的flash文档(一半时间不匹配)和C ++文档甚至没有谈论冻结之外,我在javascript中使用Box2D的文档非常少。
提及世界没有引力并且所有物体都有一些线性和角度阻尼(它应该是一种伪空间感觉)可能会有所帮助。
答案 0 :(得分:0)
我调查了Box2Djs的来源,并发现了下一件事。每次步骤Box2Djs检查身体是否在世界范围内。如果身体超出范围,则它“冻结”,即从碰撞检测中排除。有这个代码(Body.js第414行):
Freeze: function(){
this.m_flags |= b2Body.e_frozenFlag;
this.m_linearVelocity.SetZero();
this.m_angularVelocity = 0.0;
for (var s = this.m_shapeList; s != null; s = s.m_next)
{
s.DestroyProxy();
}
}
注意,此检查执行每个步骤(b2Island.js 244)。因此,如果在边界侦听器处设置e_frozenFlag,它将不执行任何操作:将在下一步设置标志。更多的是,在身体冻结之后,它失去了它的胆怯,它的形状在广泛的阶段失去了它们的代理(正如你从上面的代码中看到的那样)。看起来代理不会自动重启,因此,重置标志是不够的。
我也没有找到Box2Djs界面或解冻体的逻辑。手动执行此操作是一种肮脏的技巧,因为您应该访问BroadPhase,即Box2Djs内部。多一点,它不会帮助你,因为冻结身体会失去它的速度。但是,正如我所见,你需要继续身体移动。
接下来是解决方案。你应该防止身体冻结,以便在身体移出世界边界后保持身体模拟。它可以通过下一个技巧完成。首先,设置具有较大值的世界边界。然后,设置接触侦听器,当body接触墙壁时,执行边界违规逻辑。
如何在C ++中设置联系人监听器,你可以在那里看到:https://www.iforce2d.net/b2dtut/collision-callbacks Sory,我不知道java脚本,也不能说,如何在Box2Djs中这样做。