0

我正在做一个服务器端物理实验,用户通过套接字控制一个对象。当用户将对象移动到世界边界之外时,我遇到的问题会产生。

我正在使用通过npm.

我创建世界 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 的文档。

提到这个世界没有重力并且所有物体都有一些线性和角度阻尼(它应该是一种虚拟的空间感觉)可能会有所帮助。

4

1 回答 1

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 界面或解冻身体的逻辑中找到某处。手动执行此操作是一种肮脏的技巧,因为您应该访问 Box2Djs 内部的 BroadPhase。更重要的是,它对你没有帮助,因为在冻结身体时会失去它的速度。但是,正如我所见,你需要继续身体移动。

接下来是解决方案。您应该完全防止身体冻结,以便在身体移出世界边界后保持身体在模拟中。它可以通过下一个技巧来完成。首先,设置一些较大的值的世界边界。然后,设置接触监听器,当身体接触墙壁时,执行你的边界违规逻辑。

如何在 C++ 中设置联系人监听器,您可以在此处看到:https : //www.iforce2d.net/b2dtut/collision-callbacks 抱歉,我不知道 java 脚本,也不能说,如何在 Box2Djs 中执行此操作。

于 2013-02-05T09:39:19.200 回答