我的引力拉动算法在某些情况下表现得很奇怪

时间:2015-01-31 18:30:53

标签: c++ physics

在尝试创建我自己的物理引擎时(不要试图说服我),我决定为每个像素创建一个类,称为Particle,这个系统有一个x和ay,并且ax和y的速度,如下图所示。不幸的是,calculateGravitationalVelocity的代码在某些情况下并不遵守物理定律。例如,如果粒子的x和另一个粒子的x相同,则粒子将逼真地朝向物体落下,但是当粒子太接近时,它朝向正x射击。我只会包含类源代码,但我可以包含其他文件的源代码,尽管它部分用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速度。这是我希望代码可以做三角形的图像(对不起,它看起来不是很好,但我喜欢使用白板): Triangle Diagram

1 个答案:

答案 0 :(得分:2)

您不需要执行任何三角计算。做这样的事情:

    ...

    //Get coords of particle with gravity:
    double x2 = distantParticle.getCoords('x');
    double y2 = distantParticle.getCoords('y');

    // Get difference vector
    double rx = x2 - x1;
    double ry = y2 - y1;

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