Вопрос по box2d, objective-c, cocos2d-iphone, math – Применение эффекта вихря / водоворота в Box2d / Cocos2d для iPhone

1

Я использовалНик Веллиос & apos; руководство создать радиальную гравитацию с помощью объекта Box2D. Я в курсеСделать вихрь здесь на SO, но я не мог понять, как реализовать это в моем проекте.

Я сделал вихревой объект, который представляет собой датчик Box2D circleShape, который вращается с постоянной угловой скоростью. Когда другие объекты Box2D контактируют с этим вихревым объектом, я хочу, чтобы они вращались с той же угловой скоростью, что и вихрь, постепенно приближаясь к центру вихря. В данный момент объект притягивается к центру вихря, но он направляется прямо к центру вихря, а не вращается вокруг него медленно, как я хочу. Он также будет перемещаться в направлении, противоположном вихревому, а также при вращении вихря.

Учитывая вихрь и тело box2D, как я могу настроить тело box2d, чтобы оно вращалось вместе с вихрем, когда оно «всасывается».

Я устанавливаю вращение вихря, когда создаю его так:

b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.angle = 2.0f;
bodyDef.angularVelocity = 2.0f;

Вот как я применяю радиальную гравитацию согласноНик Веллиос & apos; образец кода.

-(void)applyVortexForcesOnSprite:(CCSpriteSubclass*)sprite spriteBody:(b2Body*)spriteBody withVortex:(Vortex*)vortex VortexBody:(b2Body*)vortexBody vortexCircleShape:(b2CircleShape*)vortexCircleShape{

    //From RadialGravity.xcodeproj
    b2Body* ground = vortexBody;
    b2CircleShape* circle = vortexCircleShape;
    // Get position of our "Planet" - Nick
    b2Vec2 center = ground->GetWorldPoint(circle->m_p);
    // Get position of our current body in the iteration - Nick
    b2Vec2 position = spriteBody->GetPosition();
    // Get the distance between the two objects. - Nick
    b2Vec2 d = center - position;
    // The further away the objects are, the weaker the gravitational force is - Nick
    float force = 1 / d.LengthSquared(); // 150 can be changed to adjust the amount of force - Nick
    d.Normalize();
    b2Vec2 F = force * d;
    // Finally apply a force on the body in the direction of the "Planet" - Nick
    spriteBody->ApplyForce(F, position);
    //end radialGravity.xcodeproj


}

Update Я думаю, что iForce2d дал мне достаточно информации, чтобы встать у меня на пути, теперь он просто настраивается. Это то, чем я сейчас занимаюсь, в дополнение к приведенному выше коду. То, что происходит, состоит в том, что тело набирает достаточную скорость, чтобы хорошо выйти из вихревой гравитации - где-то мне нужно проверить, чтобы скорость оставалась ниже этой цифры. Я немного обеспокоен тем, что не принимаю во внимание массу объекта в данный момент.

b2Vec2 vortexVelocity = vortexBody->GetLinearVelocityFromWorldPoint(spriteBody->GetPosition() );

b2Vec2 vortexVelNormal = vortexVelocity;
vortexVelNormal.Normalize();
b2Vec2 bodyVelocity = b2Dot( vortexVelNormal, spriteBody->GetLinearVelocity() ) * vortexVelNormal;

//Using a force
b2Vec2 vel = bodyVelocity;
float forceCircleX =    .6 * bodyVelocity.x;
float forceCircleY =    .6 * bodyVelocity.y;

spriteBody->ApplyForce( b2Vec2(forceCircleX,forceCircleY), spriteBody->GetWorldCenter() );

Ваш Ответ

2   ответа
2

вам просто нужно применить другую силу в соответствии с направлением вихря в текущей точке тела. Вы можете использовать b2Body :: GetLinearVelocityFromWorldPoint, чтобы найти скорость вихря в любой точке мира. Из источника Box2D:

/// Get the world linear velocity of a world point attached to this body.
/// @param a point in world coordinates.
/// @return the world velocity of a point.
b2Vec2 GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const;

Так что это будет:

b2Vec2 vortexVelocity = vortexBody->GetLinearVelocityFromWorldPoint( suckedInBody->GetPosition() );

Как только вы узнаете скорость, к которой вы стремитесь, вы можете рассчитать, сколько силы требуется, чтобы перейти от текущей скорости к желаемой скорости. Это может быть полезно:http://www.iforce2d.net/b2dtut/constant-speed

Тема в этой ссылке обсуждает только одномерную ситуацию. Для вашего случая это также по существу одномерный, если вы проецируете текущую скорость засасываемого тела на вектор vortexVelocity:

b2Vec2 vortexVelNormal = vortexVelocity;
vortexVelNormal.Normalize();
b2Vec2 bodyVelocity = b2Dot( vortexVelNormal, suckedInBody->GetLinearVelocity() ) * vortexVelNormal;

Теперь bodyVelocity и vortexVelocity будут двигаться в одном направлении, и вы сможете рассчитать, какое усилие применить. Однако, если вы просто приложите достаточно силы, чтобы точно соответствовать скорости вихря, засасываемое тело, вероятно, выйдет на орбиту вокруг вихря и никогда не будет втянуто в себя. Я думаю, вы захотите сделать силу немного меньше, и я бы уменьшил его в зависимости от силы тяжести, иначе засасываемое тело будет отброшено в сторону, как только оно коснется внешнего края вихря. Для достижения желаемого эффекта может потребоваться много настроек.

РЕДАКТИРОВАТЬ:

Сила, которую вы применяете, должна основываться наdifference между текущей скоростью (bodyVelocity) и желаемой скоростью (vortexVelocity), т.е. если тело уже движется вместе с вихрем, тогда вам не нужно применять какую-либо силу. Посмотрите на последний блок кода в подразделе «Использование сил». в ссылке, которую я дал выше. Последние три строки там делают в значительной степени то, что вам нужно, если вы замените 'avel; apos; и "требуемый Vel"; с размерами вашего тела Velocity и vortexVelocity векторы:

float desiredVel = vortexVelocity.Length();
float currentVel = bodyVelocity.Length();
float velChange = desiredVel - currentVel;
float force = body->GetMass() * velChange / (1/60.0); //for a 1/60 sec timestep
body->ApplyForce( b2Vec2(force,0), body->GetWorldCenter() );

Но помните, что это, вероятно, выведет тело на орбиту, поэтому где-то по пути вы захотите уменьшить величину применяемой силы, например. уменьшить "требуемый размер" на некоторый процент уменьшают «силу» на некоторый процент и т. д. Вероятно, было бы лучше, если бы вы могли уменьшить силу так, чтобы она была равна нулю на внешнем краю вихря.

Я обновил ответ
К тому же. То, что у вас есть, выглядит хорошо.
Это похоже на отличный ответ, сегодня вечером я попробую и дам вам знать, как у меня дела. Спасибо! glenstorey
Просто чтобы уточнить - я должен сделать это вместо того, что я уже делаю, а не в дополнение к этому? glenstorey
Спасибо, я думаю, что я уже в пути - я думаю, что мне просто нужно установить максимально возможную скорость согласно ссылке, которую вы мне дали, чтобы объекты не могли выходить из гравитации так, как они есть в данный момент. Если вы видите, что я сделал что-то явно глупое, дайте мне знать, в противном случае я буду продолжать играть и отмечу это как правильное, когда я это выясню. Еще раз спасибо за вашу помощь. glenstorey
0

в котором астероиды вращались вокруг центральной точки (между ними что-то прыгает ... это другая точка).

They are connected to the "center" body via b2DistanceJoints. You can control the joint length to make them slowly spiral inward (or outward). This gives you find grain control instead of balancing force control, which may be difficult. You also apply tangential force to make them circle the center. By applying different (or randomly changing) tangential forces, you can make the crash into each other, etc.

Я разместил более полный ответ на этот вопросВот.

Похожие вопросы