像许多关于这个主题的帖子一样,我也忙着为自己写一个精确的模拟器,用于在2D引力场中移动物体 .

我很早就决定,我会坚持 Velocity Verlet 整合,因为我希望我的物体能够保持稳定的轨道并节省能量,即使时间步长相当大 . 那么问题可能是什么呢?

好吧,到目前为止,除了一个组件外,一切似乎都表现正常 . 当我试图计算一定距离的稳定轨道的正确速度时,产生的速度将它们发送到奇数椭圆轨道,每次轨道的幅度迅速增加 .

因此,首先,以下是确定场景中下一个位置,速度和加速度的对象的方法:(目标C)

Acceleration:

-(CGVector)determineAccelerationFor:(SKObject *)object
{ // Ok, let's find Acceleration! 
    CGVector forceVector = (CGVector){0,0}; // Blank vector that we will add forces to
    for (SKObject *i in self.sceneObjects)
    {
        if (![i isEqual:object]) // Just make sure we're not counting ourselves here
        {
            CGPoint distance = [self getDistanceBetween:i.position And:object.position]; 
            float hypotenuse = sqrtf(powf(distance.x, 2)+ powf(distance.y, 2));
            float force = ((self.gravity * object.mass * i.mass)/powf(hypotenuse, 3));

            float xMagnitude = (force * distance.x);
            float yMagnitude = (force * distance.y);
            forceVector.dx += xMagnitude;
            forceVector.dy += yMagnitude;
        }
    }
    CGVector acceleration = (CGVector){forceVector.dx/object.mass, forceVector.dy/object.mass};

    return acceleration;
}

很酷,所以基本上,我只是拿一个物体,加上每个其他物体施加在它上面的所有其他力,然后将X和Y因子除以当前物体的质量以获得加速度!

接下来是Velocity . 这里我使用以下等式:

enter image description here

它的方法也非常简单:

-(CGVector)determineVelocityWithCurrentVelocity:(CGVector)v OldAcceleration:(CGVector)ao NewAcceleration:(CGVector)a
{
    float xVelocity = (v.dx + ((ao.dx + a.dx)/2) * self.timeStep);
    float yVelocity = (v.dy + ((ao.dy + a.dy)/2) * self.timeStep);
    CGVector velocity = (CGVector){xVelocity,yVelocity};
    return velocity;
}

最后,位置!这个等式是:

enter image description here

并且用以下方法确定!

-(CGPoint)determinePositionWithCurrentPosition:(CGPoint)x CurrentVelocity:(CGVector)v OldAcceleration:(CGVector)ao
{
    float xPosition = (x.x + v.dx * self.timeStep + ((ao.dx * powf(self.timeStep, 2))/2));
    float yPosition = (x.y + v.dy * self.timeStep + ((ao.dy * powf(self.timeStep, 2))/2));
    CGPoint position = (CGPoint){xPosition,yPosition};
    return position;
}

这是从下面的方法调用!!

-(void)refreshPhysics:(SKObject *)object
{

    CGPoint position = [self determinePositionWithCurrentPosition:object.position CurrentVelocity:object.velocity OldAcceleration:object.acceleration]; // Determine new Position



    SKAction *moveTo = [SKAction moveTo:position duration:0.0];
    [object runAction:moveTo]; // Move to new position

    CGVector acceleration = [self determineAccelerationFor:object]; // Determine acceleration off new position

    CGVector velocity = [self determineVelocityWithCurrentVelocity:object.velocity OldAcceleration:object.acceleration NewAcceleration:acceleration];
    NSLog(@"%@ Old Velocity: %f, %f",object.name,object.velocity.dx,object.velocity.dy);
    NSLog(@"%@ New Velocity: %f, %f\n\n",object.name,velocity.dx,velocity.dy);


    [object setAcceleration:acceleration];
    [object setVelocity:velocity];
}

好的,所以上面的那些方法决定了如何在场景中移动对象 . 现在进入最初的问题,一直存在实现稳定轨道的问题!

为了确定物体维持轨道所需的速度,我使用以下等式:
enter image description here

我实现如下:

-(void)setObject:(SKObject *)object ToOrbit:(SKObject *)parent
{
    float defaultSeparation = 200;
    // Move Object to Position at right of parent
    CGPoint defaultOrbitPosition = (CGPoint){parent.position.x + (parent.size.width/2)+ defaultSeparation,parent.position.y};
    [object setPosition:defaultOrbitPosition];

    // Determine Orbital Velocity
    float velocity = sqrtf((self.gravity * parent.mass)/(parent.size.width/2+defaultSeparation));

    CGVector vector = (CGVector){0,velocity};
    [object setVelocity:vector];
}

出于某种原因,尽管如此,我得到了糟糕的结果 . 以下是一些输出:

Information:

重力(常数)= 1000 (用于测试目的)

质量(父)= 5000 units

质量(卫星)= 1 units

分离= 224 pixels

它确定为了卫星绕父母轨道运行,速度为:

149.403580 pixels/timeStep

是必须的 . 然后检查我的计算器 .

所以这让我对可能出现的问题感到困惑 . 我记录了关于新速度和位置的所有输出,并且 does 使用我设置的速度,但是这不会在这里出错我会非常感激 .

如果有人认为我遗漏了某些东西,请告诉我,我会马上编辑 . 谢谢!