我需要帮助解决以下问题,因为我投入了很多天而没有达成可接受的解决方案。
我正在做一个Android游戏(使用libgdx),其中从上方(自上而下的视图游戏)看到主角(名为Hero)并在场上行走。 用户通过沿着屏幕移动他的手指来移动角色。手指不需要在角色上。
角色使用两个动画,一个动画向前移动(也就是说,当他的" y"大于零时,因为用户从"天空" )和另一个动画,当他向后移动时(也就是说,当他的" y"小于零时,记住我正在开发一个自上而下的视图游戏)。
最后,我需要角色始终以恒定速度移动。
简而言之,我想用手指处理这个角色,然后沿着指向我手指的方向移动它,总是一直保持恒定速度。
如果我可以设置每个增量时间的角色位置,这将非常容易,但是我使用的box2d只知道线性速度,冲动,力等等。
我尝试使用mouseJoint,其中hitbody是我的主角(Hero),而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();
...
InputProcessor:
@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事件:
GestureListener:
@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;
}
我遇到的问题是,这种运动非常不稳定,而且很脏。&#34;。角色在颤抖。
我尝试了这种方法(感谢@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;
}
我需要一个关于如何解决这个问题的建议。我的意思是,用手指沿着屏幕以恒定速度移动一个box2d字符。
非常感谢。
答案 0 :(得分:0)
计算您想要移动的方向:
dragPos.sub(currentPos);
将其标准化并乘以恒定速度:
dragPos.sub(currentPos).nor().scl(CONSTANT_SPEED);