我的引力牵引算法在某些情况下表现异常

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