Question

I'm trying to build simple particle system, I'm beginner c++ coder. I have problems probably with random number generator but I'm not sure if I did not make some logic error in my code. I tried to made simple explosion like effect. All particles starts in the same point and then going out in all directions from that point. All particles have positions aligned to pixels (I mean int numbers) and speed which is floating point number. Below I provide some relevant code:

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;

The problem is that there are visible lines aligned to x and y axis, like cross with center in emiter position. Majority of particles are near those lines, problem becomes more visible when number of particles increase, around 9000 particles lines are almost solid, also shape of explosion is not really circular, its more like square standing on the corner. Maybe I chose wrong random number gen, maybe something else is wrong, I really appreciate any help.

Was it helpful?

Solution

Your calculation of the velocity is not correct.

//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);

A note on terminology: 'speed' is a scalar value, and does not have direction. You should use the term 'velocity' to denote a vector with both direction and speed.

The problem with the above code is that the x and y values are independently generated. If you were to compare the direction radiany to the direction you actually assign to speed you would see that they don't match up.

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);

Alternatively you can generate a random velocity directly, without using sine and cosine, by creating a vector distribution. An ad hoc implementation would look like:

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.

If you wanted to get fancy you could wrap this up in a custom distribution and then your original code might look like:

my_vector_distribution<float, 2> velocity_distribution(6);

tworzona.velocity = velocity_distribution(generator);

OTHER TIPS

All particles have positions aligned to pixels (i mean int numbers) and speed which is floating point number

That is your problem. No matter what speed, your positions after updating are always snapped back to the original value (when speed < 1.0) or increase by an integer number only.

Keep your positions also as floating point values, and the problem will disappear.

I find it hard to follow your speed update process, but that could be due to your variable names. The 'usual' way is to assign an initial random horizontal and vertical speed(1), where the horizontal speed decays linearly ('air friction') and the vertical speed increases quadratically ('gravity').

(1) I guess your method of assigning an initial angle and speed is okay. But then you can split it into horizontal and vertical components and forget all vector based calculations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top