Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Нютоновская физика в моем клоне agario. (3 стр)

Нютоновская физика в моем клоне agario. (3 стр)

Поделиться

Страницы: 1 2 3

SuperInoyПостоялецwww21 июля 20160:52#30
sba
> Или ты имеешь в виду что бывает у большого шара скорость стремится к нулю?
Именно, и чтобы его сожрать игровыми средствами нужен более большой шар, который не двигается
sbaПользовательwww21 июля 201612:53#31
Я упустил офигенно важную деталь! Ведь при выстреле пуле необходимо придать начальную скорость равную скорости тела которое стреляет. Добавив эту составляющую ситуация заметно улучшилась. Выстреливаемая масса ведет себя более естественно. И что самое главное - при разделении отстреленный шар проходит почти желаемую дистанцию. Возможно надо еще поиграться со всеми коэфициентами.

Suslik
>выход — либо запуливать с бОльшей скоростью(думаю, в agar.io примерно так и делалось),
В комбинации с начальной скоростью в этом будет больше смысла - ведь это нам и даст большую скорость.

> либо на время разлёта использовать меньшее значение forceCoef
А как посчитать это время?

>либо просто использовать меньшее значение этого параметра
Уменьшить не могу, пропадает так сильно необходимая резкость.

Правка: 25 июля 2016 10:27

sbaПользовательwww27 июля 201617:25#32
#23 и #27 так и остались без ответа.

Добавлю еще вопрос, в данный момент более важный.  Для справки - как подсказал Reviri я подправил силу сопротивления, подобрал коэфициенты. Непонятным остается нюанс - при неизменных коэфициентах есть некоторый предел радиуса после которого сила сопротивления задавливает силу притяжения к курсору. Как это побороть? Просто увеличить силу притяжения, тоесть увеличисть коэфициент? У меня степенная зависимость радиуса от массы. Может более физически использовать иную зависимость?

cell.radius = m_config.cellRadiusRatio * sqrt(cell.mass / M_PI);

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

Правка: 27 июля 2016 17:59

ReviriПостоялецwww27 июля 201618:20#33
Если брать реальный мир, то сила сопротивления среды завязана на скорость перемещения тела относительно этой среды.
Когда тело относительно среды не движется, то и среда на него никакого сопротивления не оказывает, но если начать прикладывать к телу постепенно возрастающую силу, то окажется, что оно начнет двигаться только тогда, когда вынуждающая сила превысит некоторой порог, который определяется самой средой движения и площадью соприкосновения тела со средой.
То есть среда не дает телу начать двигаться оказывая этому сопротивление, хотя чисто формально у тела скорости еще нет.
В физике это хорошо разобрано на примере трения.

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

И вы все это наблюдаете у себя в игре, так как реализуете у себя физику реального мира.
Если хотите избавится от этих эффектов, то и надо избавляться от реальной физики.

sbaПользовательwww27 июля 201618:45#34
Reviri
>Если хотите избавится от этих эффектов
тут вроде как на ты заведено обращаться :)

>то и надо избавляться от реальной физики
Как ни странно, мнения разделились у форумчан. Я уже писал, что ранее у меня физики не было. Без физики я не смог решить некоторые задачи, которые с физикой реализуются сами-собой. Теперь физика есть, и я двигаюсь именно по этому пути.

>сила сопротивления среды завязана на скорость перемещения тела относительно этой среды
В #16 я пытался нафантазировать это с помощью трения, но благодаря советам ниже - успешно убрал.
Получается надо добавить к силе сопротивления составляющую зависящую от скорости. Так как скорости вроде небольшие, добавить линейную зависимость? Хотя Suslik писал что сопротивление итак уже учтено в силе притяжения. Вот не понимаю я этот нюанс. По моему мнению как-то плохо учтено, так как в моей модели точка, которая притягивает тело, постоянно от него убегает, за исключением случая, когда игрок сам ее перемещает, но это, полагаю, не в счет.

ReviriПостоялецwww27 июля 201620:09#35
Я рассказал как оно в природе устроено, а что конкретно в движке убрать, прибавить или какое конкретно значение поставить без кода сказать не могу.

sbaПользовательwww27 июля 201620:23#36
Reviri
В ближайшее время сделаю актуальную выжимку кода.
SuslikМодераторwww28 июля 20166:56#37
sba
> #23 и #27 так и остались без ответа.
я не понял, какие именно вопросы ты считаешь неотвеченными.

sba
> У меня степенная зависимость радиуса от массы. Может более физически
> использовать иную зависимость?
нормальная зависимость. только обычно наоборот — массу вычисляют из радиуса.sba
> Непонятным остается нюанс - при неизменных коэфициентах есть некоторый предел
> радиуса после которого сила сопротивления задавливает силу притяжения к
> курсору.
один из вариантов — считать не силу сопротивления, а напрямую ускорение. это — в любом случае не самый физичный вариант, но вполне сойдёт для аркадной игры. зависимость ускорения торможения от размера и скорости выбери такую, чтобы она сочеталась с ускорением от указателя таким образом, каким ты хочешь.

sbaПользовательwww29 июля 201615:21#38
Текущая версия интегрирования:
void Player::simulate(float dt)
{
  // поскипано притяжение и отталкивание тел, так как бред, и скоро я выпилю этот код
  auto dstPos = m_position + m_pointer;
  for (PlayerCell* cell : m_cells) {
    geometry::Vec2D velocity = (dstPos - cell->position) * config.playerVelocityRatio;
    if (velocity.length() > cell->maxSpeed) {
      velocity = velocity.direction() * cell->maxSpeed;
    }
    geometry::Vec2D force = (velocity - cell->velocity) * (cell->mass * config.playerForceRatio);
    cell->applayForce(force);
    cell->simulate(dt);
  }
  calcParams();
}

void Cell::applayImpulse(geometry::Vec2D value)
{
  velocity += value / mass;
}

void Cell::simulate(float dt)
{
  const auto& config = room.getConfig();
  Vec2D resistanceForce = velocity.direction() * (radius * config.resistanceRatio) + velocity * config.velocityRatio;
  force -= resistanceForce;
  Vec2D acceleration = force / mass;
  velocity += acceleration * dt;
  position += velocity * dt;
  force.zero();
}

1) Надо бы ограничить сверху силу сопротивления? Чтобы не оказалось что тело начнет двигаться в противоположную сторону.
Если да, какое должно быть ограничение?

2) Надо ли обнулять текущую скорость тела?
Если да, то когда?

Сейчас тела, которые якобы остановились и на которые не действует движущая сила (действовала и перестала; тело ранее получило импульс), очень медленно, но все-таки двигаются.

+ Показать

Правка: 29 июля 2016 15:39

sbaПользовательwww29 июля 201616:52#39
Reviri
>Поэтому это вполне законно с точки зрения реальной физики, что при увеличении размера тела увеличивается сила сопротивления и в какой-то момент она превышает вынуждающую силу и тело останавливается.
Получается надо увеличить вынуждающую силу - это порождает другую проблему озвученную в списке ниже (4).

Suslik
>один из вариантов — считать не силу сопротивления, а напрямую ускорение
Я ведь так и делаю.
>зависимость ускорения торможения от размера и скорости выбери такую, чтобы она сочеталась с ускорением от указателя таким образом, каким ты хочешь.
Пока перевариваю, без конкретного примера сложновато осилить. У меня наибольшая проблема в физике именно в понимании что с чем и как сочетается.
В первую очередь торможение нужно для тел которые получили импульс, а это все остальные тела кроме шаров игрока. К этим телам ускорение от указателя никоим образом ведь не относится.

Мне кажется что я пляшу с бубном вокруг да около. :( Если некоторые задачи по отдельности и решены, то вместе - дают вовсе не то что надо.
Список проблем:
1) Шары игрока должны резво двигаться за курсором. Я запилил силу из #1, точнее принял что это ускорение, получил силу умножив результат на массу тела. Это дало всем телам одинаковое ускорение, соответсвенно и скорость.
2) Согласно игрового дизайна чем больше тело тем меньше скорость. Возвращаемся к 1) и пытаемся считать таки силу, а не ускорение. Большие тела соответственно двигаются медленнее, но и ускорение у них становится никакое. А надо чтобы тела любого размера ускорялись одинаково быстро. Поэтому я оставил 1) как есть и ввел искуственное ограничение на максимальную скорость тела, зависящую от его радиуса. В #38 это видно в коде.
3) Уже потерял мысль для чего мне в силе сопротивления составляющая зависящая от скорости?
4) Я вроде как хочу контролировать максимальную скорость игрока. Получается увеличивая вынуждающую силу возрастает и скорость игрока, а так как я ее ограничил - ничего хорошего из этого не выходит.

sbaПользовательwww29 июля 201619:32#40
Задачу регулирования максимальной скорости игрока таки решил. Вроде работает как надо, тестил на разных максимальных массах комнаты от 50К до 250К.
void Room::modifyMass(Cell& cell, float value)
{
  cell.mass += value;
  m_mass += value;
  if (cell.mass < m_config.cellMinMass) {
    LOG_WARN << "cell.mass < m_config.cellMinMass";
  }
  cell.radius = m_config.cellRadiusRatio * sqrt(cell.mass / M_PI);
  cell.synchronized = false;
}

void Room::modifyMass(PlayerCell& cell, float value)
{
  modifyMass(static_cast<Cell&>(cell), value);
  auto minRadius = m_config.cellRadiusRatio * sqrt(m_config.cellMinMass / M_PI);
  auto maxRadius = m_config.cellRadiusRatio * sqrt(m_config.maxMass / M_PI);
  auto speedDiff = m_config.playerMaxSpeed - m_config.playerMinSpeed;
  cell.maxSpeed = m_config.playerMaxSpeed - speedDiff * (cell.radius - minRadius) / (maxRadius - minRadius);
}

}:+()___ [Smile]Постоялецwww29 июля 201621:19#41
sba
> Надо бы ограничить сверху силу сопротивления? Чтобы не оказалось что тело начнет двигаться в противоположную сторону.
Замени добавление силы на умножение скорости, т. е. вместо (псевдокод)
acceleration = -velocity * coefficient1;
velocity += acceleration * dt;
сделай
velocity *= coefficient2;
Математически это одно и то же при coefficient2 = 1 − coefficient1 * dt, но может иметь проблемы при coefficient2 < 0.
Однако конкретно это задачу можно решить точно и решением будет coefficient2 = exp(−coefficient1 * dt), которое отрицательным быть не может.
ReviriПостоялецwww29 июля 201623:50#42
sba
> Мне кажется что я пляшу с бубном вокруг да около. :( Если некоторые задачи по
> отдельности и решены, то вместе - дают вовсе не то что надо.
> Список проблем:
> 1) Шары игрока должны резво двигаться за курсором. Я запилил силу из #1, точнее
> принял что это ускорение, получил силу умножив результат на массу тела. Это
> дало всем телам одинаковое ускорение, соответсвенно и скорость.
> 2) Согласно игрового дизайна чем больше тело тем меньше скорость. Возвращаемся
> к 1) и пытаемся считать таки силу, а не ускорение. Большие тела соответственно
> двигаются медленнее, но и ускорение у них становится никакое. А надо чтобы тела
> любого размера ускорялись одинаково быстро. Поэтому я оставил 1) как есть и
> ввел искуственное ограничение на максимальную скорость тела, зависящую от его
> радиуса. В #38 это видно в коде.
> 3) Уже потерял мысль для чего мне в силе сопротивления составляющая зависящая
> от скорости?
> 4) Я вроде как хочу контролировать максимальную скорость игрока. Получается
> увеличивая вынуждающую силу возрастает и скорость игрока, а так как я ее
> ограничил - ничего хорошего из этого не выходит.


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

Реальная физика не совсем годится для прямого использования в играх.
1) Она слишком "инерционна".
Для игры нужно, чтобы тело вот сейчас начало двигаться туда, а вот сейчас остановилось.
А по физике для движения телу нужна сила, которая его разгоняет до нужной скорости, придавая ему ускорение. И надо ждать некоторое время пока скорость наберется. Если силу убрать, то только ускорение исчезает, а вот скорость остается и для остановки ее надо гасить противоположной силой, с которой та же морока.
И тут все либо начинают прикладывать большие силы для добавления резвости телам, либо просто тайком обнуляют скорость без всяких сил кодом.

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

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


Забудь на время про физику.
Возьми лист бумаги и выпиши на нем все состояния тела и что должно с ними происходить.
Например так:
1) Игрок нажал кнопку мыши. Тело должно резво разогнаться за столько-то времени до такой-то скорости.
2) Игрок отпустил кнопку. Тело должно за такое-то время остановиться.
3) Тело врезалось в препятствие. Должно произойти то-то.
4) ...

Когда все возможные состояния распишешь, то проанализируй их.
Какие-то можно оставить полностью на физику. Соударения тел или торможение об окружающую среду.
А какие-то надо будет делать читерски. Например разгон тела в направлении курсора.
Игрок, когда играет видит у тел на экране только скорости и перемещения.
Ускорение и силы, которые на них действуют он как бы подсознательно высчитывает на основе изменения именно этих наблюдаемых параметров.
То есть, если не задавать никаких сил и ускорений, а просто задать изменение скорости тела по какому-то принципу, то игрок все равно будет "ощущать", что у этого тела есть инерция, масса, на него действует какая-то сила итд.
Поэтому все ситуации, в которых тела ведут себя не так как надо разруливай не игрой коэффициентов, а жестким принуждением со стороны кода.

dimakolesУдалёнwww7 апр. 201711:50#43
Reviri
тогда уже можно сделать еще один шаг и отказаться от физики

Страницы: 1 2 3

/ Форум / Программирование игр / Физика

2001—2017 © GameDev.ru — Разработка игр