Я пытаюсь построить простую систему частиц, я начинающий c ++ кодер. Возможно, у меня проблемы с генератором случайных чисел, но я не уверен, что не допустил логической ошибки в своем коде. Я пытался сделать простой взрывоподобный эффект. Все частицы начинаются в одной точке, а затем уходят во все стороны от этой точки. Все частицы имеют позиции, выровненные по пикселям (я имею в виду целые числа) и скорость, которая является числом с плавающей запятой. Ниже я приведу соответствующий код:
std::mt19937 generator(std::time(0));//creating random number gen with seed
std::uniform_real_distribution<float> distributionx(0,6);
std::uniform_real_distribution<float> distributionkat(0,360);//distr for random number degrese
float radiany=(distributionkat(generator)*3.1415)/180;//calculating radians to provide to sin/cos function
sf::Vector2f unitvector;
tworzona.pozycja.x=this->pozycjaemitera.x;//assigning starting position, same for all particles
tworzona.pozycja.y=this->pozycjaemitera.y;
//below i calculate starting speed, as far as i know trigonometry this sure ensure that particles will fly in all directions
tworzona.speed.x=distributionx(generator)*cos(radiany);
tworzona.speed.y=distributionx(generator)*sin(radiany);
//below code should calculate unit vector in chosen direction and then i multiply it by random speed
unitvector.x=tworzona.speed.x/sqrt(pow(tworzona.speed.x,2)+pow(tworzona.speed.y,2));
unitvector.y=tworzona.speed.y/sqrt(pow(tworzona.speed.x,2)+pow(tworzona.speed.y,2));
unitvector.x=unitvector.x*distributionx(generator);
unitvector.y=unitvector.y*distributionx(generator);
tworzona.speed.x=unitvector.x;
tworzona.speed.y=unitvector.y;
Проблема в том, что есть видимые линии, выровненные по осям x и y, например, крест с центром в положении эмиттера. Большинство частиц находятся вблизи этих линий, проблема становится более заметной, когда количество частиц увеличивается, около 9000 линий частиц почти сплошные, а форма взрыва на самом деле не круглая, она больше похожа на квадрат, стоящий на углу. Может быть, я выбрал неправильное число случайных чисел, может быть, что-то еще не так, я действительно ценю любую помощь.
Ваш расчет скорости неверен.
//below i calculate starting speed, as far as i know trigonometry this sure ensure that particles will fly in all directions
tworzona.speed.x=distributionx(generator)*cos(radiany);
tworzona.speed.y=distributionx(generator)*sin(radiany);
Примечание по терминологии: «скорость» является скалярным значением и не имеет направления. Вы должны использовать термин «скорость», чтобы обозначить вектор с направлением и скоростью.
Проблема с приведенным выше кодом заключается в том, что значения x и y генерируются независимо. Если бы вы были, чтобы сравнить направление radiany
в направлении, которое вы фактически назначаете speed
Вы бы увидели, что они не совпадают.
constexpr float pi = 3.1415926535f;
std::uniform_real_distribution<float> speed_distribution(0, 6);
std::uniform_real_distribution<float> direction_distribution(0, 2*pi);
float radians = direction_distribution(generator);
float speed = speed_distribution(generator);
unitvector.x = cos(radians);
unitvector.y = sin(radians);
tworzona.velocity.x = speed * cos(radians);
tworzona.velocity.y = speed * sin(radians);
В качестве альтернативы вы можете генерировать случайную скорость напрямую, без использования синуса и косинуса, создав векторное распределение. Специальная реализация будет выглядеть так:
const double max_speed = 6.0;
const double max_squared = max_speed * max_speed;std::uniform_real_distribution<double> d(0.0, max_speed);
double x, y;
do {
x = d(generator);
y = d(generator);
} while (x*x+y*y > max_squared);
// x and y are the random velocity, uniformly distributed in all directions,
// speed uniformly distributed between 0 and max_speed.
Если вы хотите получить фантазию, вы можете обернуть это в пользовательский дистрибутив, и тогда ваш оригинальный код может выглядеть так:
my_vector_distribution<float, 2> velocity_distribution(6);
tworzona.velocity = velocity_distribution(generator);
Все частицы имеют позиции, выровненные по пикселям (я имею в виду целые числа) и скорость, которая является числом с плавающей точкой
Это твоя проблема. Независимо от скорости, ваши позиции после обновления всегда возвращаются к исходному значению (когда скорость < 1.0) или увеличить на целое число только.
Сохраняйте свои позиции также как значения с плавающей запятой, и проблема исчезнет.
Мне трудно следить за процессом быстрого обновления, но это может быть связано с именами переменных. «Обычный» способ — назначить начальную случайную горизонтальную и вертикальную скорость (1), где горизонтальная скорость уменьшается линейно («воздушное трение») и вертикальная скорость увеличивается квадратично («гравитация»).
(1) Полагаю, ваш метод задания начального угла и скорости в порядке. Но затем вы можете разделить его на горизонтальные и вертикальные компоненты и забыть все векторные вычисления.