Простая 2D ракетная динамика - PullRequest
6 голосов
/ 12 июля 2010

В настоящее время я экспериментирую с некоторыми физическими игрушками в XNA, используя библиотеку физики Farseer, однако мой вопрос относится не только к XNA или Farseer, но к какой-либо библиотеке 2D физики.

Я хотел бы добавить "ракетоподобное движение (я говорю ракетоподобное в том смысле, что это не обязательно должна быть ракета - это может быть самолет или лодка на воде или любое количество подобных ситуаций) для определенных объектов в моей 2D-сцене,Я знаю, как реализовать это с помощью кинематической симуляции, но я хочу реализовать ее с помощью динамической симуляции (то есть приложения сил во времени).Я вроде как заблудился от того, как это реализовать.

Чтобы упростить вещи, мне не нужна динамика, чтобы вращать геометрию, просто чтобы влиять на скорость тела.Я использую геометрию круга, которая не вращается в Farseer, поэтому меня интересует только скорость объекта.

Я даже не уверен, какой должна быть лучшая абстракция.Концептуально у меня есть направление, в котором тело движется в данный момент (единичный вектор), направление, в котором я хочу, чтобы оно двигалось, и значение, представляющее, насколько быстро я хочу, чтобы оно меняло направление, сохраняя скорость относительно постоянной (допустимы небольшие вариации).

Я мог бы использовать эту абстракцию напрямую или использовать что-то вроде значения «руль направления», которое контролирует, как быстро объект меняет направление (по часовой стрелке или против часовой стрелки).

Какие силы я должен приложить к телу, чтобы имитировать движение, которое я ищу?Имейте в виду, что я также хотел бы иметь возможность регулировать «тягу» ракеты на лету.

Редактировать: Как я это вижу, и поправьте меня, если я ошибаюсь, у вас есть двасилы (игнорируя основную силу тяги на данный момент):

1) У вас есть статический «плавник», который всегда направлен в том же направлении, что и тело.Если тело вращается так, что ребро не выровнено с направлением движения, сопротивление воздуха будет прикладывать силы по всей длине ребра, пропорционально углу между направлением движения и ребром.

2) У вас есть «руль», который может свободно вращаться в пределах указанного диапазона, который находится на некотором расстоянии от центра масс тела (в данном случае у нас есть круг).Опять же, когда эта плоскость не параллельна направлению движения, сопротивление воздуха вызывает пропорциональные силы по длине руля.

У меня вопрос, по-другому сформулированный, как рассчитать эти пропорциональные силы по сопротивлению воздуха противплавник и руль?

Редактировать: Для справки вот код, который я написал, чтобы проверить принятый ответ:

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main(string[] args)
    {
        float dc = 0.001f;
        float lc = 0.025f;
        float angle = MathHelper.ToRadians(45);
        Vector2 vel = new Vector2(1, 0);
        Vector2 pos = new Vector2(0, 0);
        for (int i = 0; i < 200; i++)
        {
            Vector2 drag = vel * angle * dc;
            Vector2 sideForce = angle * lc * vel;
            //sideForce = new Vector2(sideForce.Y, -sideForce.X); // rotate 90 degrees CW
            sideForce = new Vector2(-sideForce.Y, sideForce.X); // rotate 90 degrees CCW
            vel = vel + (-drag) + sideForce;
            pos = pos + vel;
            if(i % 10 == 0)
                System.Console.WriteLine("{0}\t{1}\t{2}", pos.X, pos.Y, vel.Length());
        }
    }

Когда вы отобразите вывод этой программы, вы увидитехорошая гладкая круговая кривая, именно то, что я искал!

Ответы [ 3 ]

2 голосов
/ 13 июля 2010

Если у вас уже есть код, объединяющий силу и массу с ускорением и скоростью, вам просто нужно рассчитать отдельную часть каждого из двух элементов, о которых вы говорите.

Проще говоря, яНа мгновение забудем о плавнике и просто скажем, что всякий раз, когда тело вашей ракеты находится под углом к ​​своей скорости, оно будет генерировать линейно увеличивающуюся боковую силу и сопротивление.Просто поиграйтесь с коэффициентами, пока они не будут выглядеть и чувствовать, как вы хотите.

Drag = angle*drag_coefficient*velocity + base_drag
SideForce = angle*lift_coefficent*velocity

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

2 голосов
/ 12 июля 2010

Я вдруг "получаю" это.

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


Чтобы сделать это "правильно" (для пробела):

Имитируемое тело должно быть снабжено моментом инерции вокруг его центра масс, а также должно иметь направление наведения и угловую скорость. Затем вы вычисляете угловое ускорение по приложенному импульсу и расстоянию от CoM и добавляете это к угловой скорости. Это позволяет вам вычислять текущее «наведение» корабля (если вы не используете гироскопы или парные ориентационные самолеты, вы также получаете (обычно очень небольшое) линейное ускорение).

Чтобы сгенерировать поворот, вы указываете кораблю на текущее направление движения и применяете главный привод.

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

КСТАТИ - Это может быть больше проблем, чем стоит: маневрировать ракетой в условиях свободного падения сложно (Вы можете вспомнить, что русские провалили стыковочный маневр на МКС несколько лет назад; ну это не потому что они тупые.) Если вы не сообщите нам свой вариант использования, мы не сможем дать вам совет по этому поводу.

Небольшой псевдокод, чтобы намекнуть на то, что вы получаете здесь:

rocket {
  float structuralMass;
  float fuelMass;
  point position;
  point velocity;
  float heading;
  float omega;       // Angular velocity
  float structuralI; // moment of inertia from craft
  float fuelI;       // moemnt of inertia from the fuel load

  float Mass(){return struturalMass + fuelMass};
  float I(){return struturalI + fuelI};
  float Thrust(float t);
  float AdjustAttitude(float a);
}

В результате: возможно, вам нужна версия "физики игры".


По причине, по которой я не буду вдаваться в подробности, самый эффективный способ запуска «настоящей» ракеты - это, как правило, , а не , чтобы делать постепенные повороты и медленное ускорение, но сильно нажимать когда вы захотите изменить направление. В этом случае вы получаете угол тяги, вычитая нужный вектор (полный вектор, а не единицу измерения) из текущего. Затем вы указываете это направление и доверяете всем, пока не достигнете желаемого курса.

0 голосов
/ 13 июля 2010

Представьте, что вы плывете в пустом пространстве ... И у вас в руке большой камень ... Если вы бросите камень, к вам будет приложен небольшой импульс в направлении, противоположном тому, которое вы бросаете в камень.Вы можете смоделировать свою ракету как нечто, что быстро преобразует кванты топлива в некоторую величину силы (векторную величину), которую вы можете добавить к своему вектору направления.

...