Ориентация гравитационного притяжения RK4

Я использовал RK4 для физики в небольшой 2D-игре, которую я сделал, но когда дело доходит до гравитации, все объекты притягиваются к 0,0, как я могу это изменить? (извините за отсутствие комментариев, но не успел прокомментировать)

    #include "Gravity.h"

gravity::accelerationReturn gravity::acceleration(state & state , float time) //Returns a struct instead easier to put into a vector.
{
    accelerationReturn return1;
    const float k =9.8;
    const float b = 1;
    return1.Xaccel =  -k * state.pos.getX() - b* state.vel.getX();
    return1.Yaccel = -k * state.pos.getY() - b* state.vel.getY();
    return return1;
}


gravity::derivative gravity::evaluate(state  & initial, float time, float deltaTime,derivative & Derivative)
{
    state state;
    state.pos.setXY(initial.pos.getX() + Derivative.dpos.getX()*deltaTime,
        initial.pos.getY() - Derivative.dpos.getY()*deltaTime);

    state.vel.setXY(initial.vel.getX() + Derivative.dvel.getX() * deltaTime,
        initial.vel.getY() + Derivative.dvel.getY() * deltaTime);

        derivative output;
        output.dpos.setXY(state.vel.getX(),state.vel.getY());
        output.dvel.setXY(acceleration(state,time + deltaTime).Xaccel,
            acceleration(state,time + deltaTime).Yaccel);
        return output;

}

void gravity::integrate(state & State , float time, float deltaTime)
{

    derivative a = evaluate(State ,time,0.0f,derivative());
    derivative b = evaluate(State,time,deltaTime * 0.5f,a);
    derivative c = evaluate(State,time,deltaTime * 0.5f,b);
    derivative d = evaluate(State,time,deltaTime,c);

    Vector dpdt;
    Vector dvdt;
    dpdt.setXY((1.0f/10.0f * (a.dpos.getX() + 2.0f * (b.dpos.getX() + c.dpos.getX()) + d.dpos.getX())),
              (1.0f/10.0f * (a.dpos.getY() + 2.0f * (b.dpos.getY() + c.dpos.getY()) + d.dpos.getY())));
    dvdt.setXY((1.0f/10.0f * (a.dvel.getX() + 2.0f * (b.dvel.getX() + c.dvel.getX()) + d.dvel.getX())),
               ( 1.0f/10.0f * (a.dvel.getY() + 2.0f * (b.dvel.getY() + c.dvel.getY()) + d.dvel.getY())));


    State.pos.setXY ((State.pos.getX() + dpdt.getX() * deltaTime),(State.pos.getY() + dpdt.getY() * deltaTime));
    State.vel.setXY ((State.vel.getX() + dvdt.getX() * deltaTime),(State.vel.getY() + dvdt.getY() * deltaTime));

}

cpp

#ifndef GRAVITY_H
#define GRAVITY_H

#include "2DVector.h"


class gravity :Vector 
{
private:



    float time; //current time
    float deltaTime; // previous time
public:
    struct accelerationReturn //for returning acceleration
    {
        float Xaccel;
        float Yaccel;
    };
    struct state //current state of object.
    { 
        Vector pos; //position
        Vector vel; //velocity
    };
    struct derivative
    {
        Vector dpos; // derivative of posistion is velocity.
        Vector dvel; // derivative of velocity is acceleration.
    };

    accelerationReturn acceleration (state &,float); //calculates the new acceleration
    derivative evaluate ( state & , float , float ,  derivative &); //gets derived values
    void integrate ( state &, float , float);




};
#endif

основной

#include "Gravity.h"
#include <iostream>
#include "SFML\Graphics.hpp"
#include "SFML\System.hpp"

using namespace std;

int main()
{


    gravity grav;
    gravity::state marrio;
    marrio.pos.setXY(500,500); 


    sf::RenderWindow mwindow(sf::VideoMode(800, 800), "my window");
    sf::CircleShape shape(50);
    shape.setFillColor(sf::Color(100,250,250));

    sf::Time timeC;
    float time;
    float dTime = 0.01f;

    sf::Clock timePhysics;
    while(mwindow.isOpen())
    {

               timeC = timePhysics.getElapsedTime();
               time = timeC.asSeconds();
               grav.integrate(marrio,time,dTime);
               time += dTime;
               cout<< "pos     vel"<<endl<<marrio.pos.getX()<<" "<<marrio.pos.getY()<<" "<<
                marrio.vel.getX()<<" "<<marrio.vel.getY()<<endl;
                shape.setPosition(marrio.pos.getX(),marrio.pos.getY());



                mwindow.clear();
                mwindow.draw(shape);
                mwindow.display();
    }

    system("PAUSE");
    return 0;
}

person Student123    schedule 15.12.2013    source источник
comment
Я не думаю, что здесь достаточно информации для ответа. Можете ли вы опубликовать соответствующий код?   -  person shuttle87    schedule 15.12.2013


Ответы (1)


Есть небольшая проблема с физикой, которую вы делаете в первом блоке кода. Если вы пытаетесь смоделировать гравитационное притяжение, вам нужно будет вычислить свое ускорение, используя закон всемирного тяготения Ньютона. То, что у вас есть сейчас, — это закон Гука; сила пружины с линейным сопротивлением. Чтобы сразу ответить на ваш вопрос о том, как отодвинуть центр притяжения от точки (0,0), вы можете просто изменить то, что вам нужно, включив смещение. А именно,

return1.Xaccel = -k * (state.pos.getX() - xOffset) - b* state.vel.getX();
return1.Yaccel = -k * (state.pos.getY() - yOffset) - b* state.vel.getY();

где xOffset и yOffset определяют положение (x,y) желаемого центра притяжения. Это позволило бы вам переместить источник силы, но это все еще не решило проблему, заключающуюся в том, что ваша сила является упругой, а не гравитационной (закон обратных квадратов). Для этого вам понадобится что-то похожее на следующее

float dx = state.pos.getX() - xOffset; // again xOffset is the source location
float dy = state.pos.getY() - yOffset;
float distSqrd = dx*dx + dy*dy;
float dist = sqrt( distSqrd );
return1.Xaccel = -G * mass * dx / (distSqrd * dist);
return1.Yaccel = -G * mass * dy / (distSqrd * dist);

Обратите внимание, что для того, чтобы принять во внимание направление, я умножил F = G*m1*m2/dist^2 на dx/dist и dy/dist. Это эквивалентно cos(angle) и sin(angle), где angle — это величина, которую лучше не вычислять (которая определяет направление силы). mass будет массой объекта, который притягивает ваши частицы (?), а масса частицы не учитывается, поскольку мы вычисляем только ускорение. Если вы хотите добавить линейное сопротивление обратно к ускорению, вы можете легко сделать это, что сделает орбиты намного более стабильными.

Обратите внимание, что этот код можно значительно очистить с помощью векторов. Дайте мне знать, если нужны какие-либо разъяснения.

person Nathan    schedule 16.01.2014
comment
Я использовал этот код, но, похоже, он вообще не изменился на шаре, который просто двигался с неизменной проекцией под действием гравитации. - person Student123; 20.01.2014
comment
Какие значения вы использовали для G, массы и т. д.? Кроме того, убедитесь, что вычисленный результат для dx, dy и ускорения отличен от нуля. Возможно, вы либо забыли установить значение, либо сделали G или массу слишком маленькими. - person Nathan; 21.01.2014