Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Программирование игр, графики и искусственного интеллекта > Алгоритм веревки (Физика)


Автор: Jeronimator 12.1.2006, 21:44
Многоуважаемый All!
Уже много времени бьюсь smile над одним и тем же вопросом:
smile
"Как же все-таки написать симулятор болтающейся на ветру веревки, примерно как в известной игре GISH, в которой очень все отлично реализовано и не только веревка. Только сделать это надо на простом языке программирования, типа Бэйсик или что либо похожее (без использования движков и встроенных типов =вектор=)".

А идея заключается вот в чем:
Есть игра типа симулятор летающего корабля в 2D вид сбоку. И вот хотелось бы, чтобы этой самой веревкой он мог зацепляться за что нибудь, или хотя бы просто чтобы она висела и тупо качалась на ветру, причем в зависимости от скорости корабля, она начинала болтаться в ту или иную сторону.

Я надеюсь, что все правильно объяснил, а еще больше надеюсь на то, что вы мне поможите!
Пишу эту прогу я на BlitzMax (Не надо смеяться - мне важен сам алгоритм этой веревки, так что это не зависит от Языка).

Заранее благодарен!

Автор: mr.DUDA 13.1.2006, 13:40
Верёвка - это набор сегментов, каждый из которых связан с двумя соседними (кроме крайних). Один из двух крайних сегментов закреплён, и поэтому передвигается только под воздействием точки опоры (на чём он там висит), а второй - полностью свободен. Весь алгоритм заключается в последовательной передаче движения от закреплённого крайнего сегмента к незакреплённому крайнему, и обратно, с затуханием. Форму и размер сегментов можно выбирать как угодно; например, в виде прямолинейных отрезков, или шариков (так проще). Остальное - из курса физики: скорость, ускорение, момент.

Автор: Jeronimator 13.1.2006, 19:11
Ну елки-палки, Дуда! У нас здесь урок литературы что-ли? Я впринципе догадывался, что ответ будет примерно таким, но все же надежда умирает последней. Так вот что я хочу тебе сказать - не надо думать, что я еще не открывал учебник физики и не понял, что она должна состоять из сегментов и что на каждый сегмент должна действовать свое ускорение и скорость...
Вопрос не в том, как это объяснить словами, а в том, как это написать в Бэйсике. Ты мне написал то, что впринципе я знал год назад и из чего все началось. Так вот я заходил на эху в Фиде и мне там точно так же ответили и сказали типа "Да ты ламер физику не знаешь...", а потом я им просто сказал - раз так все просто, напишите мне этот код и я признаюсь, что я ламер... так вот они НЕ НАПИСАЛИ. При мне ни разу не было написано такого кода, хотя впринципе все бонально и просто (Но все бональное и простое на листке бумаге не всегда такое же простое на деле).
Я понимаю, что прошу наверное слишком много, но все же:
"Плз, напишите мне формулу, по которой (как вы выразились, мистер Dude (Цитирую)) будет происходить последовательная передача движения от закрепленного крайнего сегмента к незакреплённому крайнему, и обратно, с затуханием". Как я понял - это всего пару строк... но они бесценны для меня, а для вас, по ходу дела просто до гениальности!
Заранее спасибо!

Автор: mr.DUDA 14.1.2006, 03:57
Спокойней, Jeronimator, без наездов. Как был задан вопрос - так и был сформулирован ответ.

Цитата(Jeronimator @ 13.1.2006, 18:11 Найти цитируемый пост)
Я понимаю, что прошу наверное слишком много, но все же:
"Плз, напишите мне формулу, по которой (как вы выразились, мистер Dude (Цитирую)) будет происходить последовательная передача движения от закрепленного крайнего сегмента к незакреплённому крайнему, и обратно, с затуханием". Как я понял - это всего пару строк... но они бесценны для меня, а для вас, по ходу дела просто до гениальности!

Гм... там на самом деле не совсем "пара строк", достаточно глянуть на физ. движок типа ODE...

Попробуем так. Каждый сегмент отрисовывается отрезком прямой линии, у которой есть начало, конец и середина. Начало совпадает с концом пред. сегмента, конец - с началом след. сегмента. Середину будем считать центром массы сегмента и назовём "шариком". Если представить все сегменты в виде таких "шариков", то можно заменить верёвку на шарики, связанные между собой силой притяжения F. Чем дальше друг от друга соседние шарики, тем выше F. Приняв массу всех шариков равной, получим ускорение шарика "a", равное равнодействующей сил (Fnext + Fprev) умноженной на приращение времени "t", где Fprev - сила, действующая от предыдущего шарика, Fnext - сила от следующего шарика. Обе силы - векторные величины, т.е. грубо говоря вычисляются отдельно по X и по Y. Ускорение расчитывается как частное от силы и массы (величина массы подбирается при отладке программы). Получив ускорение "a" и зная приращение времени "t", получаем приращение скорости шарика: dv = a * t. Это приращение добавляем к тек. скорости шарика. Скорость и ускорение - также векторные величины, как и сила. Наконец, зная текущую скорость шарика, умножаем её на "t" и получаем приращение по x и по y, которое даст изменение положения шарика по осям. Вкратце всё это можно написать вот таким псевдокодом:

Код
for i = 2 to N-1

  Fx = kF * (x[i-1] - x[i]) + kF * (x[i+1] - x[i])
  Fy = kF * (y[i-1] - y[i]) + kF * (y[i+1] - y[i])
  ax = Fx /  massa
  ay = Fy / massa
  vx[i] = vx[i] + ax * t
  vy[i] = vy[i] + ay * t
  x[i] = x[i] + vx[i] * t
  y[i] = y[i] + vy[i] * t

next i


Для первого и последнего шарика всё расчитывается отдельно, т.к. для последнего шарика нету x[i+1] и y[i+1], а для первого шарика x и y определяются сразу, по изменению координат точки опоры.

Чтобы шарики не сжались в одну точку, нужно приравнивать Fx и Fy нулю при каком-то пороговом значении (x[i-1] - x[i]) и (y[i-1] - y[i]). Кроме того, если верёвка не находится "в космосе", на каждый шарик действует постоянная сила притяжения "Fm = massa * ускорение_свободного_падения", которую нужно добавлять к Fx и Fy.

Автор: Jeronimator 14.1.2006, 14:28
Пасибsmile. Получилось конечно не симулятор веревки, а симулятор "резинки" smile . И этот вариант я тоже видел, однако решил отолкнувшись от него сделать все таки веревку, может сделаю так, что на экране будет появлятся немного другая версия этой же резинки, только уже не расстягивающаяся, а в "уме" буду вычислять примерно так, как показано на примере. Да и еще одна проблема - как избежать того, что эти шарики начинают бешенно прыгать и в конце-концов их скорость становится на столько сильной, что они улетают за приделы экрана? smile
Так не хочется помечать вопрос как решенный, может кто еще предложит вариант, как сделать именно веревку и не расстягивающуюся? smile

Автор: mr.DUDA 14.1.2006, 15:18
Цитата(Jeronimator @ 14.1.2006, 13:28 Найти цитируемый пост)
Да и еще одна проблема - как избежать того, что эти шарики начинают бешенно прыгать и в конце-концов их скорость становится на столько сильной, что они улетают за приделы экрана?

Ввести коэффициент затухания, что-то типа:

Код
vx[i] = vx[i] + ax * t
vy[i] = vy[i] + ay * t
vx[i] = vx[i] * 0.9
vy[i] = vy[i] * 0.9


Или выразить его прямо в силе.

Цитата(Jeronimator @ 14.1.2006, 13:28 Найти цитируемый пост)
Получилось конечно не симулятор веревки, а симулятор "резинки"

Нужно ограничивать перемещения "шариков" так, чтобы концы сегментов находились на одном и том же расстоянии. Например, после того как все координаты расчитаны, пробежаться по верёвке от начала до конца и "стянуть" шарики вместе:

Код
for i=1 to N-1

R = (x[i+1] - x[i]) * (y[i+1] - y[i])
if R > Rsegmenta then 
    dx = (x[i+1] - x[i]) * (Rsegmenta / R)
    dy = (y[i+1] - y[i]) * (Rsegmenta / R)
    x[i] = x[i] + dx
    y[i] = y[i] + dy
end if

next i

Автор: Jeronimator 14.1.2006, 16:51
Что-то не получается у меня, начинают все беспорядочно двигаться. Я думаю без типа "вектор" здесь не обойтись, причем BlitzMаx это позволяет. Напишу сегодня код с этим типом и постараюсь это все проделать уже с ним. Потом напишу сюда результат, ну а ежели нет, значит я в конец ламер smile

Автор: mr.DUDA 14.1.2006, 20:10
Пардон, последняя моя формула совсем неверна. Вот правильный вариант:

Код
for i = 2 to N-1

Fx = kF * (x[i-1] - x[i]) + kF * (x[i+1] - x[i])
Fy = kF * (y[i-1] - y[i]) + kF * (y[i+1] - y[i])
ax = Fx / massa
ay = Fy / massa
vx[i] = vx[i] + ax * t
vy[i] = vy[i] + ay * t
x[i] = x[i] + vx[i] * t
y[i] = y[i] + vy[i] * t

dx = x[i] - x[i-1]
dy = y[i] - y[i-1]

R = sqrt(dx*dx + dy*dy)

x = x[i] - dx / (R / Rsegment)
y = y[i] - dy / (R / Rsegment)

next i

Автор: Jeronimator 14.1.2006, 21:31
Скажи, ты проверял этот код на каком либо языке? Запускал его? Если да, то пожалуйста - вышли мне код smile
По логике я совершенно по-другому решал эту задачу. Я пытался хотя бы сэмулировать векторное представление всего этого, т.е. я брал силу натяжения к прошлому сегменту и к следующему, а потом все это дело складывал по проекциям с помощью синусов и косинусов. Правда че-то тож ничего не получалось, но хотя бы болталась что-лиsmile и круто извиваласьsmile

Автор: mr.DUDA 14.1.2006, 21:45
Цитата(Jeronimator @ 14.1.2006, 20:31 Найти цитируемый пост)
Скажи, ты проверял этот код на каком либо языке? Запускал его? Если да, то пожалуйста - вышли мне код

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

Цитата(Jeronimator @ 14.1.2006, 20:31 Найти цитируемый пост)
По логике я совершенно по-другому решал эту задачу. Я пытался хотя бы сэмулировать векторное представление всего этого, т.е. я брал силу натяжения к прошлому сегменту и к следующему, а потом все это дело складывал по проекциям с помощью синусов и косинусов. Правда че-то тож ничего не получалось, но хотя бы болталась что-ли и круто извивалась

Ну вот, значит ты мыслишь в нужном направлении smile. Только синусы и косинусы надо применять "туда, где это надо". Причина и следствие. Если сила действует на сегмент - обоснуем это. Что за сила, на какую точку действует, и почему. Если это сила обратная силе растяжения (сила, "стягивающая" верёвку), то до каких пределов она может воздействовать на сегмент? На какую точку сегмента действует - на крайнюю сначала, с конца, или в середине? Какова зависимость величины F от расстояния между сегментами? И так далее. Именно поэтому я не отвечаю на твой вопрос прямыми инструкциями, т.к. алгоритмов поведения верёвки может быть множество, всё зависит от реализации верёвки как набора объектов с собственными свойствами и поведением. А синусы и косинусы можно приложить куда угодно, получая при этом совершенно безумный, непредсказуемый результат. Чтобы что-то получилось как надо, нужно продумать свои действия (то бишь, поведение верёвки) от начала до конца, и реализовать их программно.

Автор: Jeronimator 14.1.2006, 21:49
Могу ли я в этой теме попросить тебя дать хотя бы пару ссылок, где можно по этой теме разобраться. Может есть сайтик где люди и занимаются тем, что физику на комп переводят? Было бы очень как полезно, или это ОффТопик?

Автор: mvdr 14.1.2006, 22:05
Цитата(Jeronimator @ 14.1.2006, 21:49 Найти цитируемый пост)

что физику на комп переводят?
поверь мне, залезь на любой форум физического факультета любого ВУЗа и тебе смогут помочь с физикой данной задачи.
Набери в поисковике "физический факультет" и сначинай исследовать просторы.

Автор: mr.DUDA 14.1.2006, 22:51
Цитата(Jeronimator @ 14.1.2006, 20:49 Найти цитируемый пост)
Может есть сайтик где люди и занимаются тем, что физику на комп переводят

Есть очень крутой бесплатный open-source движок http://ode.org/, есть аналог - http://www.physicsengine.com/, есть http://www.tokamakphysics.com/. Во всех этих физических движках реализован API, позволяющий создать и управлять объектами типа "верёвка" и не только.

Автор: Jeronimator 14.1.2006, 23:16
Я не знаю, что такое API и не освоил пока С++, так что сижу на BlitzMax, а перешел сюда с Паскаля и Бэйсика. Так что движок для меня тяжелоsmile

Автор: mr.DUDA 14.1.2006, 23:24
Цитата(Jeronimator @ 14.1.2006, 22:16 Найти цитируемый пост)
Я не знаю, что такое API и не освоил пока С++, так что сижу на BlitzMax, а перешел сюда с Паскаля и Бэйсика. Так что движок для меня тяжело

Дык он же платный, этот BlitzMax, или я не прав smile ?
Можешь зайти http://www.devmaster.net/engines/ и выбрать любой бесплатный движок по вкусу, там есть как минимум http://www.devmaster.net/engines/list.php?fid=6&sid=6 на BASIC-языке.

Автор: Jeronimator 14.1.2006, 23:41
Он у меня крякнутый, но наполовину, т.е. работать он мне дает, а вот обнавляться через инет не хочетsmile.
А про движки я говорил... дело в том, что для меня важно не то, что это можно сделать и чтоб оно работало, а чтобы я понял, как это пишется на языке программирования. Вот в чем смысл! Пока не узнаю, дальше не пойдуsmile А мне скоро на С++ переходитьsmile И все равно его с начала изучать буду, без библиотек и движков...

Автор: $tatic 20.1.2006, 22:10
Может быть, что для веревки и не надо делать никаких движков? Любая веревка / провод / т.д. прогибается под действием силы тяжести по закону гиперболического косинуса (y=cosh x). Надо только правильно рассчитывать функцию для конкретного момента времени.

Автор: mr.DUDA 21.1.2006, 12:34
Цитата($tatic @ 20.1.2006, 21:10 Найти цитируемый пост)
Может быть, что для веревки и не надо делать никаких движков? Любая веревка / провод / т.д. прогибается под действием силы тяжести по закону гиперболического косинуса (y=cosh x). Надо только правильно рассчитывать функцию для конкретного момента времени.

Вот бы ещё конкретный пример...

Автор: Innuendo 25.1.2006, 18:33
веревка это кусок граффика.
подойди к училки математики (если ты с ней в ладах, и ты ещё в школе), и пораспрашивай.
там короче на граффиках всё взаимосвязано... каждая переменная за что-то отвечает (за наклон, отступ от осей, угол разъежания и т.д и т.п).
В твоём случае это может быть кусок параболлы, а может быть кусок гипперболы.
Поэксперементируй, выясни какая именно часть больше подходит, какая формула граффика, и в зависимости от чего будет изменяться наклон и направления.
ну и те значения уже будут изменяться взависимости от движения твоего корабля.

Автор: mr.DUDA 25.1.2006, 22:10

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)