【问题标题】:Player swinging with a rope, How do I calculate the tension of the rope to apply on the player? (Monogame)玩家用绳子摆动,我如何计算施加在玩家身上的绳子的张力? (单人游戏)
【发布时间】:2021-12-30 22:38:54
【问题描述】:

这是我第一次在这里提问,很抱歉,如果我没有说出需要的一切,请随时询问更多信息。

基本上,我正在创建一个使用加速度移动的玩家角色,如下所示:

velocity.X += movingDir * acceleration - friction * velocity.X;
velocity.Y += gravityScale * gravityVector //Vector2(0,9.81f * gravityScale)
if (normalMouvement)
    velocity.X = Math.Clamp(velocity.X, -maxSpeed, maxSpeed);

我想让玩家在按下 A 时附在绳子上,然后绕着绳子摆动直到他松开 A。玩家已经有了一个起始速度,该速度会随着绳子摆动而改变(例如,如果我按下左键向右摆动时,我会摆动得更慢)。绳子的附着位置已经定义好了。

(我知道这是高级艺术哇)

我在阅读 this article 后尝试过这样做:

if (Input.GetKeyDown(Keys.A))
        distanceToGrapplingPoint = (Platformer.Map.data.grapplingPoints[0].Pos - Pos).Length();
if (Input.GetKey(Keys.A))
        Swing();
//this is in the Update Method

private void Swing()
    {
        Vector2 distance = Vector2.Normalize(Platformer.Map.data.grapplingPoints[0].Pos - Pos) * distanceToGrapplingPoint;
        
        Vector2 gravityTension = -Vector2.Normalize(distance) * gravityVector.Y * gravityScale * distance.Y / distance.Length();
        Vector2 centripetalForce = distance * gravityVector.Y * gravityScale * (velocity / distance.Length()) * (velocity / distance.Length());
        
        Vector2 totalTension = gravityTension + centripetalForce;
        
        velocity += totalTension;
    }

但我的玩家直接飞入了抓斗点。我不想只设置玩家的位置并收工,而是实际计算绳索的张力以使代码更加模块化。

感谢您的帮助!

【问题讨论】:

  • 你是在做绳索还是刚性固定距离?

标签: c# game-physics monogame


【解决方案1】:

您的代码相对于Normalize()Length() 有很多冗余

distanceToGrapplingPoint 是与枢轴保持的距离。这个值是必需的,因为摩擦在起作用:

要保持圆周运动路径,所施加的力必须是 X 和 Y 之间的恒定平方比,X^2 + Y^2 = distanceToGrapplingPoint,X 轴上的摩擦力会使该比率失衡,导致Y 值以实物形式减小,从而使摆锤在每次通过时变短。


让我们看一下围绕单位圆的 90 度步长,在数学坐标中(y+,0 度开始 = 右):

(1,0)->(0,1)->(-1,0)->(0,-1)

现在用 X 代替 1 并查看模式:

(X,0)->(0,X)->(-X,0)->(0,-X)

注意 X 如何变成 Y,然后又变成 X。

现在如果 X 因摩擦而减少(仅在 X 的部分是 X 分量时)当摩擦减少的值变为 Y 值时,Y 被限制为与 X 值匹配。

由于上述原因,以下代码中提出的解决方案应用了一个校正步骤来保持循环路径。结果接近物理准确,在我们称之为足够接近的游戏中。


获得真正准确的结果;钟摆需要自己的速度(超出此答案的范围。)

我们将angleToGrapplingPoint定义为方向单位向量,在您的代码中:Vector2.Normalize(distance)

注意:向心力不存在,它是绳索的外部限制,用于对抗牛顿第一运动定律:运动中的物体将继续该运动,除非受到外力(在这种情况下为张力)的作用。

private void Swing()
    {
        Vector2 angleToGrapplingPoint = Vector2.Normalize(Platformer.Map.data.grapplingPoints[0].Pos - Pos);
        
        // enforce the distance constraint 
        // for fixed pole not rope for 1-179 degree angles
        Pos = angleToGrapplingPoint * distanceToGrapplingPoint;

        // subtract the gravity component is will be adjusted for tension and 
        //  added back in the next line
        Velocity -= gravityVector.Y * gravityScale; 
        
        // Apply the tension to gravity by adding an X component while diminishing the Y component(depending on angle)
        Velocity += gravityVector.Y * gravityScale * angleToGrapplingPoint;


        // Add the constraint to keep in a circle x*x + y*y = r*r
        // or Cos^2(x) + Sin^2(y) * gravity + velocity ~=  distanceToGrapplingPoint;
        // This code limits the movement to the bounds of the circle
        Velocity -= angleToGrapplingPoint * angleToGrapplingPoint gravityVector.Y * gravityScale;
    }

此代码在物理上可能不是 100% 准确,但应该是接近的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多