我正在使用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);
}
}
Vector2 velocity = this.getBody().getLinearVelocity();
preX = velocity.x / (Math.abs(velocity.x));
preY = velocity.y / (Math.abs(velocity.y));
if (Math.abs(velocity.x) < 5) {
this.body.setLinearVelocity(preX * 5, velocity.y);
}
if (Math.abs(velocity.y) < 5) {
this.body.setLinearVelocity(velocity.x, preY * 5);
}
编辑:
currentVelocity = bulletBody.getLinearVelocity();
if (currentVelocity.len() < speed
|| currentVelocity.len() > speed + 0.25f) {
velocityChange = Math.abs(speed
- currentVelocity.len());
currentVelocity.set(currentVelocity.x
* velocityChange, currentVelocity.y
* velocityChange);
bulletBody.applyForce(currentVelocity,
bulletBody.getWorldCenter());
}
b2Vec2 currentDirection = body->GetLinearVelocity();
currentDirection.Normalize();
body->SetLinearVelocity( 5 * currentDirection );
需要注意的是,这只能在球自由运动时进行。如果它正在弹跳到墙壁或其他物体中间,这将会导致问题。因此,在执行此操作之前,您需要确保它没有接触任何物体。如果GetContactList()返回null,则表示该物体没有接触任何物体。
这种调整应该足够便宜,可以在每个时间步骤中进行,但由于速度直到再次碰撞才会改变,因此您甚至可以在弹跳结束后仅执行一次。您可以使用联系人侦听器,在EndContact回调中检查球是否仍在接触某些物体,如果没有,请在时间步骤结束后标记该物体以进行调整。
我在我的更新函数中使用这个来保持球的速度。
speed = ball.getLinearVelocity().length()
maxSpeed = 10;
if (speed > maxSpeed ){
ball.setLinearDamping(0.5);
}
else if (speed < maxSpeed) {
ball.setLinearDamping(0.0);
}
if (speed < maxSpeed ){
var currentVelocity = ball.getLinearVelocity();
currentVelocity.set(currentVelocity.x * 1.1, currentVelocity.y * 1.1);
ball.applyForce(currentVelocity,ball.getWorldCenter());
}