Как рассчитать движение 2D-объекта, приводимого в движение несколькими двигателями?

#game-physics #motion

#игра-физика #движение

Вопрос:

Работаем над игрой с объектами, сделанными из соединенных квадратов (вспомните фигуры из тетриса). Каждый квадрат может случайным образом иметь двигатель, толкающий его в одном направлении: вверх, вниз, влево, вправо. Как я могу вычислить общую скорость X / Y и вращение объекта в 2D пространстве?

Редактировать: добавлено изображение, чтобы показать несколько примеров объектов

введите описание изображения здесь

Комментарии:

1. На самом деле это не вопрос программирования; это линейная алгебра, дискретная математика и капля вероятности (если вы считаете случайность существенной). Лучше на math.SE .

Ответ №1:

Простая сила, приложенная к объекту

Объект имеет положение x , y , вращение r и дельты dx , dy и dr .

  object { x : 0, y : 0, r : 0, dx : 0, dy : 0, dr : 0, mass : 1000};
  

Сила находится в location x, y и в a direction .

Сила делится на составляющие ускорения и углового ускорения на величину, на которую сила направлена к центру масс и по касательной к центру мат. Затем разделить на массу для ускорения и массу * расстояние от центра масс для углового ускорения. Эти ускорения затем добавляются к дельтам x, y и r. Эти дельты затем используются для обновления местоположения объекта и поворота.

 object.x  = object.dx;
object.y  = object.dy;
object.r  = object.dr;
  

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

Код — это Javascript, а более подробная информация — в комментариях.

 // apply force in direction to object at the center of mass
function applyForceCenter(object, force, direction){ 
    force /= object.mass; 
    object.dx  = Math.cos(direction) * force;
    object.dy  = Math.sin(direction) * force;
}

// apply force to object at location in direction 
// location is absolute
function applyForce(object, location, force, direction){ 
    // get the relative position of the force to the center of mass (COM)
    var ox = object.x - location.x;
    var oy =  object.y - location.y;
    var radius = Math.sqrt(ox * ox   oy * oy); // get distance from COM
    if(radius <= 1e-6){  // if too close use simple calcs
        applyForceCenter(object,force,direction);
        return;
    }
    // get the angle from the applied force to the center
    var toCenter = Math.atan2(oy, ox); // Yes y is first
    // the difference between the direction of force and direction to center
    var pheta = toCenter - direction;
    // reduce force by mass
    // Get the component parts of the force
    var Fv = Math.cos(pheta) * force; // The amount of the force that
                                      // contributes to acceleration
                                      // along the line to the center
    var Fr = Math.sin(pheta) * force; // The amount of the force that
                                      // contributes to angular acceleration
                                      // along the tangent from the center
    // Reduce acceleration by mass 
    Fv /= object.mass;
    // get the x,y components of that force along the line from where
    // it is applied to the center of mass
    object.dx  = Math.cos(toCenter) * Fv;
    object.dy  = Math.sin(toCenter) * Fv;

    // reduce angular acceleration by distance and mass
    Fr /= (radius  * object.mass);                                        
    object.dr  = Fr; // add the change of rtoation

}
  

Комментарии:

1. Отличное объяснение! Спасибо.

Ответ №2:

Ну, может быть, я чего-то не понимаю, но это выглядит как простая физика. Здесь вы должны помнить 2 вещи :

 sum of forces = mass * acceleration (or a(t 1) = Ftotal / m) and
v(t 1) = v(t)   a(t 1) * dt
  

Итак, в вашем случае вы могли бы просто использовать что-то вроде

 f_total = vec2(0, 0)
// Eventually add some other external forces

for_each thruster do
    f_total  = thruster.force_vector

new_velocity = old_velocity   (f_total / mass) * dt
  

Комментарии:

1. Я не думаю, что это учитывало бы центр масс для получения желаемого эффекта. Например, первый объект переместился бы вперед и немного влево, потому что правый двигатель не выровнен с центром масс.

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

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