我的引力牵引算法在某些情况下表现异常
My Gravitational Pull Algorithm behaves Oddly in Certain Situations
在尝试创建我自己的物理引擎时(不要试图说服我不要这样做),我决定为每个像素创建一个 class,称为 Particle
,这个系统有一个 x和 y,以及 x 和 y 速度,如下所示。不幸的是,calculateGravitationalVelocity
的代码在某些情况下不遵守物理定律。例如,如果粒子的 x 值与另一个粒子的 x 值相同,则该粒子会真实地落向对象,但当粒子靠得太近时,它会向正 x 方向砰砰作响。我只打算包含 class 源代码,但我可以包含其他文件的源代码,尽管它部分是用 SFML
编写的
Particle.cpp:
#include <iostream>
#include <string>
#include <math.h>
class Particle
{
private:
//Coords:
double x, y;
//Velocities:
double xVelocity = 0;
double yVelocity = 0;
//Material:
std::string material = "Generic";
//Mass:
double mass = 0;
public:
//Coords:
void setCoords(double, double);
float getCoords(char);
//Velocities:
void giveVelocity(char, float);
void setVelocity(char, float);
float getVelocity(char);
//Gravitational Velocity:
void calculateGravitationalVelocity(Particle);
//Material:
void setMaterial(std::string);
std::string getMaterial();
//Mass:
void setMass(double);
double getMass();
//Update:
void update();
};
//Coords:
void Particle::setCoords(double newX, double newY)
{
x = newX;
y = newY;
}
float Particle::getCoords(char axis)
{
if (axis == 'x')
{
//return floor(x);
return x;
}
else if (axis == 'y')
{
//return floor(y);
return y;
}
}
//Velocities:
void Particle::giveVelocity(char axis, float addedVelocity)
{
if (axis == 'x') {xVelocity = xVelocity + addedVelocity;}
else if (axis == 'y') {yVelocity = yVelocity + addedVelocity;}
}
void Particle::setVelocity(char axis, float newVelocity)
{
if (axis == 'x') {xVelocity = newVelocity;}
else if (axis == 'y') {yVelocity = newVelocity;}
}
float Particle::getVelocity(char axis)
{
if (axis == 'x') {return xVelocity;}//floor(xVelocity);}
else if (axis == 'y') {return xVelocity;}//floor(yVelocity);}
}
//Gravitational Velocity (Where the problems probably are):
void Particle::calculateGravitationalVelocity(Particle distantParticle)
{
//Physics constants:
const double pi = 3.14159265359; //Pi
const double G = 0.00000000006673; //Gravitational Constant (or Big G)
//Big Triangle Trigonometry:
//Get coords of moving particle:
double x1 = x;
double y1 = y;
//Get coords of particle with gravity:
double x2 = distantParticle.getCoords('x');
double y2 = distantParticle.getCoords('y');
if (x1 != x2)
{
//Work out the angle:
double A = atan((y2 - y1) / (x2 - x1)) * 180 / pi;
//Remove the minus sign:
A = fabs(A);
//Small Triangle Trigonometry:
//Work out the hypotenuse of the big triangle:
double hyp = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
//Work out the gravitational field (hyp of small triangle):
long double gravitationalField = G * (distantParticle.getMass() / pow(hyp, 2));
//For testing purposes:
//std::cout << "X: " << (cos(A) * gravitationalField) / 1000 << std::endl;
//std::cout << "Y: " << (sin(A) * gravitationalField) / 1000 << std::endl;
//Work out the X velocity:
xVelocity = xVelocity + (cos(A) * gravitationalField) / 1000;
//Work out the Y velocity:
yVelocity = yVelocity + (sin(A) * gravitationalField) / 1000;
}
else
{
//Work out the hypotenuse of the big triangle:
double hyp = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
//Work out the gravitational field (hyp of small triangle):
long double gravitationalField = G * (distantParticle.getMass() / pow(hyp, 2));
yVelocity = yVelocity + gravitationalField / 1000;
}
}
//Material:
void Particle::setMaterial(std::string newMaterialType)
{
material = newMaterialType;
}
std::string Particle::getMaterial()
{
return material;
}
//Mass:
void Particle::setMass(double newMass)
{
mass = newMass;
}
double Particle::getMass()
{
return mass;
}
//Update:
void Particle::update()
{
x = x + xVelocity;
y = y + yVelocity;
}
很抱歉这个问题很开放,它可能在某个地方违反了规则,但我找不到它。用于计算的代码主要使用两个三角形来制作 x 和 y 速度。这是我希望代码可以作为三角形执行的操作的图像(抱歉,它看起来不太好,但我喜欢使用白板):
您不需要进行任何三角函数计算。
...
//Get coords of particle with gravity:
double x2 = distantParticle.getCoords('x');
double y2 = distantParticle.getCoords('y');
// Get difference vector
double rx = x1 - x2;
double ry = y1 - y2;
// square of distance
double r2 = rx * rx + ry * ry;
// distance
double r = sqrt (r2);
if (r != 0) {
// normalize difference vector
double ux = rx / r;
double uy = ry / r;
// acceleration of gravity
double a = - G * distantParticle.getMass() / r2;
xVelocity += a * ux / 1000;
yVelocity += a * uy / 1000;
}
}
在尝试创建我自己的物理引擎时(不要试图说服我不要这样做),我决定为每个像素创建一个 class,称为 Particle
,这个系统有一个 x和 y,以及 x 和 y 速度,如下所示。不幸的是,calculateGravitationalVelocity
的代码在某些情况下不遵守物理定律。例如,如果粒子的 x 值与另一个粒子的 x 值相同,则该粒子会真实地落向对象,但当粒子靠得太近时,它会向正 x 方向砰砰作响。我只打算包含 class 源代码,但我可以包含其他文件的源代码,尽管它部分是用 SFML
Particle.cpp:
#include <iostream>
#include <string>
#include <math.h>
class Particle
{
private:
//Coords:
double x, y;
//Velocities:
double xVelocity = 0;
double yVelocity = 0;
//Material:
std::string material = "Generic";
//Mass:
double mass = 0;
public:
//Coords:
void setCoords(double, double);
float getCoords(char);
//Velocities:
void giveVelocity(char, float);
void setVelocity(char, float);
float getVelocity(char);
//Gravitational Velocity:
void calculateGravitationalVelocity(Particle);
//Material:
void setMaterial(std::string);
std::string getMaterial();
//Mass:
void setMass(double);
double getMass();
//Update:
void update();
};
//Coords:
void Particle::setCoords(double newX, double newY)
{
x = newX;
y = newY;
}
float Particle::getCoords(char axis)
{
if (axis == 'x')
{
//return floor(x);
return x;
}
else if (axis == 'y')
{
//return floor(y);
return y;
}
}
//Velocities:
void Particle::giveVelocity(char axis, float addedVelocity)
{
if (axis == 'x') {xVelocity = xVelocity + addedVelocity;}
else if (axis == 'y') {yVelocity = yVelocity + addedVelocity;}
}
void Particle::setVelocity(char axis, float newVelocity)
{
if (axis == 'x') {xVelocity = newVelocity;}
else if (axis == 'y') {yVelocity = newVelocity;}
}
float Particle::getVelocity(char axis)
{
if (axis == 'x') {return xVelocity;}//floor(xVelocity);}
else if (axis == 'y') {return xVelocity;}//floor(yVelocity);}
}
//Gravitational Velocity (Where the problems probably are):
void Particle::calculateGravitationalVelocity(Particle distantParticle)
{
//Physics constants:
const double pi = 3.14159265359; //Pi
const double G = 0.00000000006673; //Gravitational Constant (or Big G)
//Big Triangle Trigonometry:
//Get coords of moving particle:
double x1 = x;
double y1 = y;
//Get coords of particle with gravity:
double x2 = distantParticle.getCoords('x');
double y2 = distantParticle.getCoords('y');
if (x1 != x2)
{
//Work out the angle:
double A = atan((y2 - y1) / (x2 - x1)) * 180 / pi;
//Remove the minus sign:
A = fabs(A);
//Small Triangle Trigonometry:
//Work out the hypotenuse of the big triangle:
double hyp = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
//Work out the gravitational field (hyp of small triangle):
long double gravitationalField = G * (distantParticle.getMass() / pow(hyp, 2));
//For testing purposes:
//std::cout << "X: " << (cos(A) * gravitationalField) / 1000 << std::endl;
//std::cout << "Y: " << (sin(A) * gravitationalField) / 1000 << std::endl;
//Work out the X velocity:
xVelocity = xVelocity + (cos(A) * gravitationalField) / 1000;
//Work out the Y velocity:
yVelocity = yVelocity + (sin(A) * gravitationalField) / 1000;
}
else
{
//Work out the hypotenuse of the big triangle:
double hyp = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
//Work out the gravitational field (hyp of small triangle):
long double gravitationalField = G * (distantParticle.getMass() / pow(hyp, 2));
yVelocity = yVelocity + gravitationalField / 1000;
}
}
//Material:
void Particle::setMaterial(std::string newMaterialType)
{
material = newMaterialType;
}
std::string Particle::getMaterial()
{
return material;
}
//Mass:
void Particle::setMass(double newMass)
{
mass = newMass;
}
double Particle::getMass()
{
return mass;
}
//Update:
void Particle::update()
{
x = x + xVelocity;
y = y + yVelocity;
}
很抱歉这个问题很开放,它可能在某个地方违反了规则,但我找不到它。用于计算的代码主要使用两个三角形来制作 x 和 y 速度。这是我希望代码可以作为三角形执行的操作的图像(抱歉,它看起来不太好,但我喜欢使用白板):
您不需要进行任何三角函数计算。
...
//Get coords of particle with gravity:
double x2 = distantParticle.getCoords('x');
double y2 = distantParticle.getCoords('y');
// Get difference vector
double rx = x1 - x2;
double ry = y1 - y2;
// square of distance
double r2 = rx * rx + ry * ry;
// distance
double r = sqrt (r2);
if (r != 0) {
// normalize difference vector
double ux = rx / r;
double uy = ry / r;
// acceleration of gravity
double a = - G * distantParticle.getMass() / r2;
xVelocity += a * ux / 1000;
yVelocity += a * uy / 1000;
}
}