0

我需要帮助解决以下问题,因为我已经投入了很多天而没有找到可接受的解决方案。

我正在做一个 Android 游戏(使用 libgdx),从上面可以看到主角(名为 Hero)(自上而下的视图游戏)并在田野上行走。用户通过在屏幕上移动他的手指来移动角色。手指不需要放在角色上。

角色使用两个动画,一个动画在他向前移动时(即当他的“y”大于零时,因为用户从“天空”看游戏),另一个动画在他向后移动时(即当他的“y”小于零,记住我正在开发一个自上而下的视图游戏)。

最后,我需要角色始终以恒定的速度移动。

简而言之,我想用手指处理角色并将其移动到标记我手指的方向,始终保持恒定速度。

如果我可以在每个增量时间设置角色的位置,这将非常容易,但我使用的是 box2d,它只知道线性速度、脉冲、力等。

我尝试使用 mouseJoint,其中 hitbody 是我的主角(英雄),而 groundBody 是一个看不见的身体。

// Invisible zero size ground body
// to which we can connect the mouse joint
Body groundBody;
BodyDef bodyDef = new BodyDef();
groundBody = world.createBody(bodyDef);

/* player is an instance of my Hero's class, which has a box2d body and
update, draw methods, etc.
*/
hitBody = player.getB2body(); 
...

输入处理器:

@Override
public boolean touchDown(int i, int i1, int i2, int i3) {
        gameCam.unproject(testPoint.set(i, i1, 0));
        MouseJointDef def = new MouseJointDef();
        def.bodyA = groundBody;
        def.bodyB = hitBody;
        def.collideConnected = true;
        def.target.set(testPoint.x, testPoint.y);
        def.maxForce = 1000.0f * hitBody.getMass();
        mouseJoint = (MouseJoint) world.createJoint(def);
        hitBody.setAwake(true);
}

@Override
public boolean touchUp(int i, int i1, int i2, int i3) {
    player.getB2body().setLinearVelocity(0,0);

    // if a mouse joint exists we simply destroy it
    if (mouseJoint != null) {
        world.destroyJoint(mouseJoint);
        mouseJoint = null;
    }
    return false;
}

@Override
public boolean touchDragged(int i, int i1, int i2) {
    // if a mouse joint exists we simply update
    // the target of the joint based on the new
    // mouse coordinates
    if (mouseJoint != null) {
        gameCam.unproject(testPoint.set(i, i1, 0));
        mouseJoint.setTarget(target.set(testPoint.x, testPoint.y));
        evaluateMovementDirection();
    }
    return false;
}

private void evaluateMovementDirection() {
    float vy = player.getB2body().getLinearVelocity().y;
    float vx = player.getB2body().getLinearVelocity().x;

    // Test to Box2D for velocity on the y-axis.
    // If Hero is going positive in y-axis he is moving forward.
    // If Hero is going negative in y-axis he is moving backwards.
    if (vy > 0.0f) {
        player.onMovingUp(); // In draw, I'll use a "moving forward" animation
    } else if (vy < 0.0f) {
        player.onMovingDown(); // In draw, I'll use a "movieng backwards" animation
    } else {
        player.onStanding(); // vy == 0 In draw, I'll use a texture showing my Hero standig.
    }
}

我遇到的问题是,如果我非常快地移动手指,角色移动得非常快。我希望角色始终以恒定速度移动。

我尝试的另一种方法是使用 pan 事件:

手势监听器:

@Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
    /*
    * DeltaX is positive when I move my finger to the left, negative otherwise.
    * DeltaY is positive when I move my finger down, negative otherwise.
    */

    // In b2body y-axes sign is the opposite.
    deltaY = -deltaY;

    // DeltaX and deltaY are in pixels, therefore delta is in metres.
    Vector2 delta = new Vector2(deltaX / Constants.PPM, deltaY / Constants.PPM);

    // Deltas too small are discarded
    if (delta.len() > Constants.HERO_SENSIBILITY_METERS) {
        /*
        * origin.x = player.getB2body().getPosition().x
        * origin.y = player.getB2body().getPosition().y
        *
        * destination.x = origin.x + delta.x
        * destination.y = origin.y + delta.y
        *
        * To go from origin to destination we must subtract their position vectors: destination - origin.
        * Thus destination - origin is (delta.x, delta.y).
        */
        Vector2 newVelocity = new Vector2(delta.x, delta.y);

        // Get the direction of the previous vector (normalization)
        newVelocity.nor();

        // Apply constant velocity on that direction
        newVelocity.x = newVelocity.x * Constants.HERO_LINEAR_VELOCITY;
        newVelocity.y = newVelocity.y * Constants.HERO_LINEAR_VELOCITY;

        // To avoid shaking, we only consider the newVelocity if its direction is slightly different from the direction of the actual velocity.
        // In order to determine the difference in both directions (actual and new) we calculate their angle.
        if (Math.abs(player.getB2body().getLinearVelocity().angle() - newVelocity.angle()) > Constants.HERO_ANGLE_SENSIBILITY_DEGREES) {
            // Apply the new velocity
            player.getB2body().setLinearVelocity(newVelocity);
            evaluateMovementDirection();
        }
    } else {
        // Stop
        player.getB2body().setLinearVelocity(0, 0);
        evaluateMovementDirection();
    }
    return true;
}

我遇到的问题是运动非常不稳定和“脏”。角色在颤抖。

我尝试了这种方法(感谢@hexafraction)。使用此代码,我的角色在屏幕上移动得更加流畅。它并不完美,但它是……

@Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
    /*
    * DeltaX is positive when I move my finger to the left, negative otherwise.
    * DeltaY is positive when I move my finger down, negative otherwise.
    * Both are in pixels, thus to get meters I must divide by Constants.PPM.
    */

    // In b2body y-axes sign is the opposite.
    deltaY = -deltaY;

    /*
    * origin.x = player.getB2body().getPosition().x
    * origin.y = player.getB2body().getPosition().y
    *
    * destination.x = origin.x + deltaX / Constants.PPM
    * destination.y = origin.y + deltaY / Constants.PPM
    *
    * To go from origin to destination we must subtract their position vectors: destination - origin.
    * Thus, destination - origin is (deltaX / Constants.PPM, deltaY / Constants.PPM).
    */
    candidateVelocity.x = deltaX / Constants.PPM;
    candidateVelocity.y = deltaY / Constants.PPM;

    // Get the direction of the previous vector (normalization)
    candidateVelocity.nor();

    // Apply constant velocity on that direction
    candidateVelocity.x = candidateVelocity.x * Constants.HERO_LINEAR_VELOCITY;
    candidateVelocity.y = candidateVelocity.y * Constants.HERO_LINEAR_VELOCITY;

    // Linear interpolation to avoid character shaking
    heroVelocity.lerp(candidateVelocity, Constants.HERO_ALPHA_LERP);

    // Apply the result
    player.getB2body().setLinearVelocity(heroVelocity);

    // Depending on the result, we change the animation if needed
    evaluateMovementDirection();
}
return true;
}

我需要一个关于如何解决这个问题的建议。我的意思是,用我的手指在屏幕上以 CONSTANT SPEED 移动一个 box2d 角色。

非常感谢。

4

1 回答 1

0

计算您要移动的方向:

dragPos.sub(currentPos);

对其进行归一化并与恒速相乘:

dragPos.sub(currentPos).nor().scl(CONSTANT_SPEED);
于 2017-12-27T06:51:33.657 回答