Как мне создавать частицы, которые реагируют на игрока и врагов?

38

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

Игра представляет собой космический шутер сверху вниз (с довольно интересным поворотом), и я ожидаю получить эффект туманности, через который игрок будет летать. Я действительно хочу попробовать это приятное тактильное ощущение сотен частиц, движущихся с пути корабля игрока, когда он летит в них. Что-то вроде того, как частицы движутся по пути игрока в Geomtry Wars на XBLA.

Я опытный программист, когда дело доходит до C ++. Однако я не знаю, как начать реализовывать этот эффект. У кого-нибудь есть какие-нибудь крутые идеи или варианты дизайна, которые я мог бы рассмотреть? Не стесняйтесь отвечать на любой интересующей вас глубине.

Мэтт Макдональд
источник

Ответы:

65

Это классная идея. Вам понадобится какой-то диффузионный градиент вокруг вашего корабля. Я могу подумать о трех физических моделях:

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

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

  3. Вы хотите быстро отодвинуть частицы от корабля по мере приближения, как в (1) и (2), но как только корабль исчезнет, ​​частицы будут медленно восстанавливать равновесие, чтобы быть равноудаленными в вашем следе.

Общее для всех трех решений : вам нужно иметь диффузное поле, которое движется вместе с вашим кораблем. В этом примере мы сделаем это круглым. Затем вы обнаруживаете вектор, называемый v1, между кораблем и каждой частицей в этом регионе. Оттолкни свою частицу вдоль этого вектора. То, насколько сильно вы оттолкнете его, будет зависеть от расстояния до корабля: используйте 1 - v1.magnitude. Эта формула даст вам линейную прочность, однако вы можете изменить ее, чтобы использовать что-то еще, например, круговую кривую прочности, которая уменьшает прочность по направлению к краям. Это выглядело бы так, как будто вокруг корабля был сферический, а не круглый градиент давления.

Для решения 1 : Все, что вы сейчас делаете, это изменяете позицию рендеринга этой частицы (то есть позицию спрайта) при каждом обновлении рендеринга этим вектором. Поскольку вы делаете это таким образом, это чисто эффект рендеринга и не влияет на фактическое положение частицы в мире. Таким образом, вы добавляете мировую позицию к смещению рендеринга (v1), и теперь у вас есть хорошо смещенные частицы, когда вы проходите мимо них или рядом с ними, и плавно поворачиваете частицы, когда вы проходите мимо (позади вас).

Для решения 2 : Вместо того, чтобы просто применять v1 к позиции просмотра, применяйте ее при каждом обновлении логики , к позиции частицы. Так, p1.position += v1. Итак, вы прикладываете ускоряющую силу к частице, которая переводится в скорость. Вероятно, вы захотите, чтобы скорость каждой частицы была уменьшена, чтобы они постепенно замедлялись и останавливались после того, как вы пройдете. Вы можете видеть, как это решение приведет к скоплению частиц в вашей туманности, потому что они никогда не будут перераспределяться. Я уверен, что это не очень реалистично, поскольку туманности имеют градиенты давления, какими бы слабыми они ни были в реальности.

Для решения 3: То же, что (2), но в этом случае вам придется перерассеять ваши частицы. Это легко сделать, используя метод грубой силы, но так как это всего лишь частицы и, следовательно, приятный глаз, вам, вероятно, не нужно покрывать огромную область интереса (возможно, только радиус playerPosition + maxPlayerSpeedPerTick или любой другой прямоугольная область ограничивает это, для логических целей). Каждая частица будет прикладывать силу к другой частице в интересующей области. Они будут применять силы, основываясь, опять же, на расстоянии друг от друга. Рассчитайте все межчастичные силы за один проход по интересующей области, а затем примените все силы за один проход. Наконец, убедитесь, что вы выполняете эту межчастичную обработку только для частиц с нулевой скоростью. И как только любая конкретная частица достигает некоторой минимальной скорости,

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

инженер
источник
Мате, к сожалению, в настоящее время у меня нет репутации, чтобы поднять ваш ответ (и я смогу сделать это только один раз, а это меньше, чем оно того заслуживает). Вы абсолютно прибили то, что я ищу в вашем первом решении. Фантастический ответ. Честно. Благодарность!
Мэтт Макдональд
Полное удовольствие, Мэтт, это хороший вопрос и стоит потрудиться!
инженер
Я также решил, что с очень небольшим изменением в коде я мог бы применить это к меньшим астероидам в поясе. Еще раз спасибо.
Мэтт Макдональд