0

我看了一堆类似的问题,我似乎找不到一个特别回答我的问题的问题。我正在编写一个简单的 3d 游戏,我试图让玩家在我的地图上拾取和移动实体。我本质上想要获得一个速度矢量,它将“推动”物理对象远离玩家的眼睛,无论他们在哪里看。这是在另一个游戏中执行此操作的示例(玩家在他的眼前拿着一个椅子实体)。

为此,我找出玩家的眼睛角度,然后从角度获取前向矢量,然后计算对象的速度。这是我的工作代码:

void Player::PickupOtherEntity( Entity& HoldingEntity )
{
    QAngle eyeAngles = this->GetPlayerEyeAngles();
    Vector3 vecPos = this->GetEyePosition();
    Vector3 vecDir = eyeAngles.Forward();

    Vector3 holdingEntPos = HoldingEntity.GetLocation();

    // update object by holding it a distance away
    vecPos.x += vecDir.x * DISTANCE_TO_HOLD;
    vecPos.y += vecDir.y * DISTANCE_TO_HOLD;
    vecPos.z += vecDir.z * DISTANCE_TO_HOLD;

    Vector3 vecVel = vecPos - holdingEntPos;
    vecVel = vecVel.Scale(OBJECT_SPEED_TO_MOVE);

    // set the entity's velocity as to "push" it to be in front of the player's eyes
    // at a distance of DISTANCE_TO_HOLD away
    HoldingEntity.SetVelocity(vecVel);
}

这一切都很棒,但我想转换我的数学,以便我可以施加冲动。我不想为对象设置一个全新的速度,而是想在其现有速度上“添加”一些速度。所以假设我有它当前的速度,我需要什么样的数学来“添加”速度?这本质上是一个游戏物理问题。谢谢!

4

3 回答 3

0

基本牛顿/达朗贝尔物理学规定:

derivate(position)=velocity
derivate(velocity)=acceleration

也向后:

integrate(acceleration)=velocity
integrate(velocity)=position

因此,对于您的引擎,您可以使用:

矩形求和而不是积分(积分的数值解)。定义时间常数dt [seconds],即更新之间的间隔(计时器或 1/fps)。所以更新代码(必须定期调用 every dt

vx+=ax*dt;
vy+=ay*dt;
vz+=az*dt;
 x+=vx*dt;
 y+=vy*dt;
 z+=vz*dt;

在哪里:

  • a{x,y,z} [m/s^2]是实际加速度(在您的情况下,方向矢量缩放为a=Force/mass
  • v{x,y,z} [m/s]是实际速度
  • x,y,z [m]是实际位置

    1. 这些值必须初始化a,v为零并x,y,z初始化位置
    2. 所有对象/玩家...都有自己的变量
    3. 句号由完成v=0; a=0;
    4. 物体的驱动只能通过改变a
    5. 在碰撞镜像v矢量的情况下通过碰撞normal

    并且可能乘以一些k<1.0(例如 0.95)来说明影响时的能量损失

g您可以通过添加矢量来添加重力或任何其他力场:

vx+=ax*dt+gx*dt;
vy+=ay*dt+gy*dt;
vz+=az*dt+gz*dt;

你也可以添加摩擦和任何你需要的东西

PS。角度也一样,只是使用angle/omega/epsilon/I而不是x/a/v/m

用角度明确I表示(pitch,yaw,roll)绕质心旋转

于 2013-10-08T07:37:16.470 回答
0

对于一个常数 F,脉冲在技术上是 FΔt。这里我们可能想要假设 aΔt,因为质量是无关紧要的。如果你想制作一个冲动的动画,你必须决定速度的变化应该是什么以及需要多长时间。它变得非常复杂。

老实说,冲动不是正确的做法。相反,最好设置一个恒定的pick_up_velocity(人们不倾向于使用冲动来捡东西),并在每次物体上升velocity.y时刷新位置,直到它达到正确的水平:

while(entPos.y < holdingEntPos.y)
{
    entPos.y += pickupVel.y;
   //some sort of short delay
}

至于漂浮在玩家眼前,设置某种类型的 EyeMovementEvent,它也将正确的位置变化发送到玩家持有的任何实体。

如果我错过了什么,而这就是你已经在做的事情,请记住,当人类施加冲动时,通常会在很短的时间内非常高的加速度,远小于一帧。反正你不会在游戏中看到它。

于 2013-06-08T17:32:40.253 回答
0

一个非常简单的实现可能是这样的:

velocity(t+delta) = velocity(t) + delta * acceleration(t)
acceleration(t) = force(t) / mass of the object

速度、加速度和力是向量。t、delta 和质量标量。

这仅适用于较小且等间距的增量。您本质上试图实现的是使用经典力学模拟物体。

于 2013-06-07T18:39:06.647 回答