我正在使用 AndEngine/Box2d 开发游戏。我有一个在屏幕上弹跳的球。我已经通过施加相反的力成功地让它忽略了重力,但它有一个在初始脉冲后减速的租赁,即使弹性设置为 1。本质上我想:
如果(速度 <一个数字) 在运动方向上施加力或脉冲(哪个更好?)
我该怎么做?
最佳答案
不幸的是,球正在与其他物体相互作用,因此设置速度不起作用,但我找到了解决方案!
利用力量和相当广泛的三角学,我终于想出了:
private static class Ball extends Sprite {
Body body;
public Ball(final float pX, final float pY, final ITextureRegion pTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager) {
super(pX, pY, pTextureRegion, pVertexBufferObjectManager);
body = PhysicsFactory.createCircleBody(mPhysicsWorld, this, BodyType.DynamicBody, PhysicsFactory.createFixtureDef(0, 1, 0));
body.applyLinearImpulse(((float)5),(float) 5, body.getWorldCenter().x, body.getWorldCenter().y);
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(this, body, true, true));
scene.attachChild(this);
}
@Override
protected void onManagedUpdate(final float pSecondsElapsed) {
body.applyForce(new Vector2(0,-SensorManager.GRAVITY_EARTH), new Vector2(body.getWorldCenter()));
float vx = body.getLinearVelocity().x, vy = body.getLinearVelocity().y, vr=(float) Math.sqrt(vx*vx+vy*vy);
float t= (float) Math.atan(Math.abs(vy/vx));
if(vr<destroyerVelocity){
if(vx>0&&vy<0)
body.applyForce((float) ((destroyerVelocity-vr)*Math.cos(t)*body.getMass()), (float) (-(destroyerVelocity-vr)*Math.sin(t)*body.getMass()), body.getWorldCenter().x, body.getWorldCenter().y);
else if(vx>0&&vy>0)
body.applyForce((float) ((destroyerVelocity-vr)*Math.cos(t)*body.getMass()), (float) ((destroyerVelocity-vr)*Math.sin(t)*body.getMass()), body.getWorldCenter().x, body.getWorldCenter().y);
else if(vx<0&&vy>0)
body.applyForce((float) (-(destroyerVelocity-vr)*Math.cos(t)*body.getMass()), (float) ((destroyerVelocity-vr)*Math.sin(t)*body.getMass()), body.getWorldCenter().x, body.getWorldCenter().y);
else if(vx<0&&vy<0)
body.applyForce((float) (-(destroyerVelocity-vr)*Math.cos(t)*body.getMass()), (float) (-(destroyerVelocity-vr)*Math.sin(t)*body.getMass()), body.getWorldCenter().x, body.getWorldCenter().y);
}
if(vr>destroyerVelocity){
if(vx>0&&vy<0)
body.applyForce((float) (-(vr-destroyerVelocity)*Math.cos(t)*body.getMass()), (float) ((vr-destroyerVelocity)*Math.sin(t)*body.getMass()), body.getWorldCenter().x, body.getWorldCenter().y);
else if(vx>0&&vy>0)
body.applyForce((float) (-(vr-destroyerVelocity)*Math.cos(t)*body.getMass()), (float) (-(vr-destroyerVelocity)*Math.sin(t)*body.getMass()), body.getWorldCenter().x, body.getWorldCenter().y);
else if(vx<0&&vy>0)
body.applyForce((float) ((vr-destroyerVelocity)*Math.cos(t)*body.getMass()), (float) (-(vr-destroyerVelocity)*Math.sin(t)*body.getMass()), body.getWorldCenter().x, body.getWorldCenter().y);
else if(vx<0&&vy<0)
body.applyForce((float) ((vr-destroyerVelocity)*Math.cos(t)*body.getMass()), (float) ((vr-destroyerVelocity)*Math.sin(t)*body.getMass()), body.getWorldCenter().x, body.getWorldCenter().y);
}
super.onManagedUpdate(pSecondsElapsed);
}
}
本质上,它所做的是创建一个物体并对其施加冲动以使其移动(出于某种原因,效果比力强得多)。在每次更新时,都会施加一个与重力相反的力,以保持球在空中(本质上是漂浮的)。弹性设置为 1,因此碰撞几乎是完全弹性的。现在是棘手的部分:我计算了 x 和 y 速度(分别为 vx 和 vy)并使用它们计算合成速度 (vr) 和它们在 (t) 中行进的角度。
如果 vr 小于我想要的速度 (destroyerVelocity),则会施加一个力将其恢复到驱逐舰速度。由于 F=mv/t 而我只使用 t=1,因此在一个方向上施加的力等于所需的速度 - 实际速度 * x/y(即 cos/sin)* 物体的质量。如果物体在正 x 方向和负 y 方向运动,则施加 (x,-y) 的力,依此类推。
为了使速度尽可能接近 destroyerVelocity,我必须在相反方向施加一个力,如果它恰好大于 destroyerVelocity。这是以相同的方式完成的,只是使用了相反的力。
运行合成速度的日志语句(驱逐舰速度为 7),它的内容如下:6.900001、6.9995001、7.00028、7.13005,...
虽然球有时会飙升至 15 或 20,但通常只需要 2 或 3 圈就可以将球打到 7 的 +- .5 以内,这对我来说已经足够了!希望这可以帮助其他人寻找同样的东西。
关于android - 我如何在物体行进的方向上对物体施加力 (Box2D)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11257462/