【问题标题】:How to get the distance that a body has moved during a box2D world step?如何获得在 box2D 世界步骤中身体移动的距离?
【发布时间】:2017-01-13 04:42:28
【问题描述】:

我正在尝试为我的游戏循环实现线性插值和固定时间步长。我正在使用 libGDX 引擎和 box2D。我试图找出模拟在这样的世界步骤中移动我的角色身体的量:

  old_pos = guyBody.getPosition();
  world.step(STEP_TIME, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
  new_pos = guyBody.getPosition();
  printLog(new_pos.x-old_pos.x);

这每次都返回 0。模拟效果很好,身体每一步都在移动。

附加代码:

@Override
public void render(float delta) {

    accumulator+=delta;
    while (accumulator>=STEP_TIME){
        accumulator-=STEP_TIME;
        stepWorld();
    }
    alpha = accumulator/STEP_TIME;
    update(delta);
    //RENDER 
}


    private void stepWorld() {
       old_pos = guyBody.getPosition();
       old_angle = guyBody.getAngle() * MathUtils.radiansToDegrees;
       world.step(STEP_TIME, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
       new_angle = guyBody.getAngle() * MathUtils.radiansToDegrees;
       new_pos = guyBody.getPosition();
    }

我正在尝试使用 alpha 来检查我在物理步骤之间的距离,以便我可以插入 Sprite 的位置。

谢谢!

【问题讨论】:

  • 试试printLog(new_pos.x)printLog(old_pos.x),值是多少?
  • 它们更新,但它们始终相同: I/OUT:: -54.899673 I/OUT:: -54.899673 I/OUT:: -- I/OUT:: -54.229126 I/OUT :: -54.229126 I/OUT:: -- I/OUT:: -53.55858 I/OUT:: -53.55858 I/OUT:: --
  • 注意 new_pos 和 old_pos 是一样的吗??
  • 是的,它们不应该不同吗?
  • 是的,它应该基于您的要求,但显然涉及到一个循环,只需将“old_pos”存储在循环之外。您提供的代码有限,因此很难看到发生了什么。

标签: java libgdx box2d


【解决方案1】:

Body 的 getPosition 方法返回 Vector 引用 - 这意味着您不是按值复制它,而是仅将位置对象上的“指针”分配给 old_pos/new_pos。但是,您在step 之前分配它一次,然后在step 之后分配它,所有这两个变量都保持相同的对象step 之后的状态。

您需要做的是按值复制位置向量 - 为此,您可以使用 Vector 的 cpy() 方法。

你的代码应该是这样的

old_pos = guyBody.getPosition().cpy();
world.step(STEP_TIME, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
new_pos = guyBody.getPosition().cpy();
printLog(new_pos.x-old_pos.x);

如果您不使用 y 坐标,您还应该考虑仅在浮点类型变量中保留 x 以不复制整个对象(但它不应该真正影响您的性能)。

【讨论】:

  • 这很有意义,谢谢。我试试看。
【解决方案2】:

虽然接受的回复确实回答了我的问题,但我想添加一些我在尝试使其工作时发现的信息,我希望我在开始时就知道这些信息。

如果您要使用固定时间步进行物理计算(您应该这样做),您还应该在物理步之间插入(或外推)Sprite 的位置。在我的代码中,屏幕的渲染频率高于世界的步进频率:

@Override
public void render(float delta) {

    accumulator+=delta;
    while (accumulator>=STEP_TIME){
        accumulator-=STEP_TIME;
        stepWorld();
    }
    alpha = accumulator/STEP_TIME;
    update(delta);
    //RENDER using alpha
}

为避免移动对象的渲染抖动,请在其位置渲染精灵或纹理,并通过 alpha 进行修改。由于 alpha 是您的累加器与步进时间的比率,因此它始终介于 0 和 1 之间。

然后你需要知道你的身体在一个步骤中移动了多少。这可以通过接受的答案或使用身体速度来完成:

newPos = oldPos + body.getLinearVelocity()*STEP_TIME*alpha

然后只需在新位置渲染 Sprite,您应该会看到在大多数帧速率下以固定时间步长平滑移动。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多