我使用AndEngine/Box2d開發遊戲。我有一個彈跳在屏幕周圍的球。我已經成功地做它通過使用相反的力無視重力,但它有一個租賃的初始衝動後慢,甚至設置爲1的彈性基本上我想:我如何在身體的行走方向上施加力量(Box2D)?
如果(速度< 一編號) 在運動方向上施加力或衝動(哪個更好?)
我該怎麼做?
我使用AndEngine/Box2d開發遊戲。我有一個彈跳在屏幕周圍的球。我已經成功地做它通過使用相反的力無視重力,但它有一個租賃的初始衝動後慢,甚至設置爲1的彈性基本上我想:我如何在身體的行走方向上施加力量(Box2D)?
如果(速度< 一編號) 在運動方向上施加力或衝動(哪個更好?)
我該怎麼做?
好可惜,球與其他對象,因此設定速度沒有工作的互動,但我已經找到了解決辦法!
使用力量和相當廣泛的三角函數,我終於想出了:
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爲7)和讀取類似:6.900001,6.9995001,7.00028,7.13005,...
雖然球會秒殺喜歡15或20有時候,它通常只需要2或3個循環就可以達到7以內的+ - .5,這對我來說已經足夠了!希望這可以幫助其他人尋找相同的東西。
要在你可以使用下面的代碼的移動方向施加持續的力。
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());
}
這是你必須寫在管理更新方法或更新處理器的另一個代碼。
如果球不與任何其他交互然後使用SetLinearVelocity應該罰款,這將是比計算力/衝量(C++)簡單:
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());
}
使CPU佔用更少的一種方法是將第一個if語句更改爲:if((destroyerVelocity-vr)> acceptedVelocityError),並將第二個if語句更改爲:if((vr-destroyerVelocity)> acceptedVelocityError)。然後,您將acceptedVelocityError設置爲.5。這樣,如果速度與期望速度相差小於0.5,則不會施加力。它加快了fps很多。 – rphello101