解冻Box2Djs中的物体或阻止退出世界

时间:2013-02-04 05:44:31

标签: javascript node.js box2d physics

我正在进行服务器端物理实验,用户通过套接字控制对象。当用户将对象移出世界的边界时,我遇到了问题。

我正在通过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的文档非常少。

提及世界没有引力并且所有物体都有一些线性和角度阻尼(它应该是一种伪空间感觉)可能会有所帮助。

1 个答案:

答案 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中这样做。