Java中的偏心向量在轨道移动时不精确
我正在用java编写一个小的libgdx程序,这个程序的灵感来自Kerbal Space程序,我现在正在编写一个类来控制将对其施加力的对象。这些对象中的每一个都有一个速度矢量,该矢量由力矢量改变 该程序每秒运行60帧左右,每帧对改变速度的力进行1000次计算。(不过,我经常使用这个号码)。现在,这个程序非常简单,每次迭代都会施加和计算的唯一作用力来自地球Java中的偏心向量在轨道移动时不精确,java,libgdx,game-physics,Java,Libgdx,Game Physics,我正在用java编写一个小的libgdx程序,这个程序的灵感来自Kerbal Space程序,我现在正在编写一个类来控制将对其施加力的对象。这些对象中的每一个都有一个速度矢量,该矢量由力矢量改变 该程序每秒运行60帧左右,每帧对改变速度的力进行1000次计算。(不过,我经常使用这个号码)。现在,这个程序非常简单,每次迭代都会施加和计算的唯一作用力来自地球 forcedub = ((gravConstanat*parentBody.getMass())/Math.pow(loc.distance
forcedub = ((gravConstanat*parentBody.getMass())/Math.pow(loc.distance(parentBody.getLoc()),2));
force = new Point2D(((-1)*forcedub*Math.cos(a)),((-1)*forcedub*Math.sin(a)));
这会明显地改变速度,调整位置并继续循环。这个过程运行得很好,看起来很稳定。我已经连续几天没有运行它了,但即使在相对较高的偏心率下,轨道看起来也很稳定。不幸的是,我需要能够加快这个过程,这样就不需要2天的实时到达月球。所以我需要一个系统,使轨道“在轨道上”,而不需要重新计算每次迭代的力。一旦乘数值设置得太高,轨道就会分离
好消息是我已经有了这个系统,我只是不能在两者之间切换
我需要轨道上的一些值来在我的系统中执行此操作。(我知道有些值有点多余,但事实就是如此)
- 半长轴
- 半短轴
- 偏心矢量
- 偏心率
- 真异常
- 重点信息
公共类对象{
字符串名;
质感;
雪碧雪碧;
B体父母体;
点2D loc;
点2D水平;
公共布尔加速;
双乘数;
静态双重力=6.67*数学功率(10,-11);
双半a,半b,ecc,w;
保护双t;
保护双质量;
保护双旋转;
保护双焦点;
公共对象(Cbody cb){
质量=1;
乘数=1;
旋转率=0;
父体=cb;
加速度=假;
cb.addKlob(本);
loc=新点2D((parentBody.getX()-900_000f),
(parentBody.getY());
vel=新点2D(02526.733);
sprite=textureAtlas.createSprite(名称);
setOrigin(sprite.getWidth()/2,sprite.getHeight()/2);
烘焙();
}
公共无效更新(浮动dt){
oneXupdate(dt);
烘焙();
}
私有无效oneXupdate(浮动dt){
int timesLooped=1000;
双a;
双钳;
点2D力;
点2D速度;
双dx;
双dy;
dt=dt/时间循环;
for(int i=0;i
对于精确浮动,double可能不是最好的数据类型-
public void bake(){
double velSq = Math.pow(vel.distance(0,0),2);
double r = loc.distance(parentBody.getLoc());
double gm = gravConstanat*parentBody.getMass();
Point2D posr = new Point2D(loc.getX()-parentBody.getX(), loc.getY()-parentBody.getY());
Point2D calc1 = posr.scale((velSq/gm));
Point2D calc2 = vel.scale((dotProd(posr,vel)/gm));
Point2D calc3 = posr.scale(1/r);
Point2D eccVecc = (calc1.minus(calc2)).minus(calc3);
ecc = eccVecc.distance(0,0);
w = Math.toRadians(90)-(Math.atan2(eccVecc.x(),eccVecc.y()));
semiA = (gm*r)/(2*gm - r*velSq);
semiB = semiA*(Math.sqrt((1-Math.pow(ecc,2))));
focus = findFocus(semiA,semiB);
System.out.println("ecc " + ecc + " W " + w + " SEMI A " + semiA);
System.out.println();
}
public class Klobject {
String name;
TextureAtlas textureAtlas;
Sprite sprite;
Cbody parentBody;
Point2D loc;
Point2D vel;
public boolean acceleration;
double MULTIPLIER;
static double gravConstanat = 6.67*Math.pow(10,-11);
double semiA, semiB, ecc, w;
protected double t;
protected double mass;
protected double rotateRate;
protected double focus;
public Klobject(Cbody cb){
mass = 1;
MULTIPLIER = 1;
rotateRate = 0;
parentBody = cb;
acceleration = false;
cb.addKlob(this);
loc = new Point2D((parentBody.getX() - 900_000f ),
(parentBody.getY()));
vel = new Point2D(0,2526.733);
sprite = textureAtlas.createSprite(name);
sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
bake();
}
public void update(float dt){
oneXupdate(dt);
bake();
}
private void oneXupdate(float dt){
int timesLooped = 1000;
double a;
double forcedub;
Point2D force;
Point2D velout;
double dx;
double dy;
dt = dt/timesLooped;
for (int i = 0; i < timesLooped; i++){
velout = vel.scale(MULTIPLIER);
dx = (dt*velout.getX());
dy = (dt*velout.getY());
loc = new Point2D(loc.getX()+dx, loc.getY()+dy);
a = Math.atan2(loc.getX()-parentBody.getX(), loc.getY()-parentBody.getY());
a = Math.toRadians(90)-a;
forcedub = ((gravConstanat*parentBody.getMass())/Math.pow(loc.distance(parentBody.getLoc()),2));
force = new Point2D(((-1)*forcedub*Math.cos(a)),((-1)*forcedub*Math.sin(a)));
force = force.scale(MULTIPLIER*MULTIPLIER);
velout = velout.plus(new Point2D(force.getX()*dt,force.getY()*dt));
vel = velout.scale(1/MULTIPLIER);
}
}
public void bake(){
double velSq = Math.pow(vel.distance(0,0),2);
double r = loc.distance(parentBody.getLoc());
double gm = gravConstanat*parentBody.getMass();
Point2D posr = new Point2D(loc.getX()-parentBody.getX(), loc.getY()-parentBody.getY());
Point2D calc1 = posr.scale((velSq/gm));
Point2D calc2 = vel.scale((dotProd(posr,vel)/gm));
Point2D calc3 = posr.scale(1/r);
Point2D eccVecc = (calc1.minus(calc2)).minus(calc3);
ecc = eccVecc.distance(0,0);
w = Math.toRadians(90)-(Math.atan2(eccVecc.x(),eccVecc.y()));
semiA = (gm*r)/(2*gm - r*velSq);
semiB = semiA*(Math.sqrt((1-Math.pow(ecc,2))));
focus = findFocus(semiA,semiB);
System.out.println("ecc " + ecc + " W " + w + " SEMI A " + semiA);
System.out.println();
}
public double findFocus(double a, double b){
return Math.sqrt(a*a - b*b);
}
public double getX(){
return loc.getX();
}
public double getY(){
return loc.getY();
}
public void setRotateRate(double rr){rotateRate = rr;}
public String getName(){
return name;
}
public Sprite getSprite(){
return sprite;
}
public void setMultiplier(double mult){
MULTIPLIER = mult;
}
public Point2D getLoc(){
return loc;
}
public void setLoc(Point2D newLoc){
loc = newLoc;
}
public double dotProd(Point2D a, Point2D b){
return a.x()*b.x() + a.y()+b.y();
}
}