【问题标题】:C# Vector to Quaternion Rotation IssueC# 向量到四元数的旋转问题
【发布时间】:2012-10-13 09:30:15
【问题描述】:

我有一个相当复杂的问题。本质上,我有一个跟踪玩家位置的对象,使用 LOS 算法始终飞向玩家当前位置。

但是我遇到了一个问题,因为我试图让对象向玩家的方向发射子弹。该对象使用纯矢量数学向玩家移动,但考虑到我的函数如何运作,子弹需要使用四元数。

那么,如果一个对象向玩家移动,我如何进行四元数旋转,子弹函数可以使用它来创建也向玩家移动且源为对象的子弹?

我绘制跟随玩家的对象的函数:

private void drawEnemy(GameTime gameTime)
{
    angle += 0.1f;

    velocity = Vector3.Normalize(xwingPosition - enemyPos) * 0.02f;

    enemyPos = enemyPos + velocity;
    enemyWorldMatrix = Matrix.CreateRotationY(angle) * Matrix.CreateTranslation(enemyPos);
    DrawObject(enemy, enemyWorldMatrix, viewMatrix, projectionMatrix);

    //enemyRotation = GetRotation(xwingPosition, enemyPos);

    //Quaternion additionalRot = Quaternion.CreateFromAxisAngle(new Vector3(0, -1, 0), -0.1f) * Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), -0.1f);
    //enemyRotation *= additionalRot;

    double currentTime = gameTime.TotalGameTime.TotalMilliseconds;
    if (currentTime - enemyLastBulletTime > 1000)
    {
        EnemyBullet newBullet = new EnemyBullet();
        newBullet.position = new Vector3(enemyPos.X + 0.2f, 71, enemyPos.Z + 0.2f);
        newBullet.t = 0.01f;
        newBullet.proportion = newBullet.t / 120;
        newBullet.playerPosition = xwingPosition;
        newBullet.enemyPosition = enemyPos;
        newBullet.currentAccel = 0.025f;
        enemyBulletList.Add(newBullet);

        enemyLastBulletTime = currentTime;
    }
}

如您所见,它使用矢量数学来跟踪并朝玩家移动。

如您所见,我正在尝试创建项目符号。子弹使用我希望我正确创建的四元数旋转。

在我编写的第一个函数创建子弹后,我的更新子弹位置的函数。

private void UpdateEnemyBulletPositions()
{
    for (int i = 0; i < enemyBulletList.Count; i++)
    {
        EnemyBullet currentBullet = enemyBulletList[i];
        currentBullet.t += 0.01f;
        currentBullet.position = enemyPos + (Vector3.Normalize(currentBullet.playerPosition - currentBullet.enemyPosition) * currentBullet.proportion);
        MoveForward(ref currentBullet.position, currentBullet.rotation, 0.04f + (currentBullet.currentAccel));
        enemyBulletList[i] = currentBullet;

        BoundingSphere bulletSphere = new BoundingSphere(currentBullet.position, 0.05f);
        CollisionType colType = CheckCollision(bulletSphere);
        if (colType != CollisionType.None)
        {
            enemyBulletList.RemoveAt(i);
            i--;

            if (colType == CollisionType.Target)
                gameSpeed *= 1.05f;
        }
    }
}

xwingPosition 是玩家当前的位置。

enemyPos是跟随玩家的物体的当前位置

这个问题显示在我刚刚准备的这个 youtube 剪辑中......

http://www.youtube.com/watch?v=PnkCVKdfN9Y

我认为问题在于将 t 设置为总经过的毫秒数,而不是从 0 开始的计数器。问题是,我不知道每次制作子弹时如何从 0 开始计数器。

【问题讨论】:

  • 我不确定您是否需要旋转任何东西来计算子弹的轨迹。当然,如果你的子弹不是球形的,你就需要旋转来绘制它们的形状。这是你的问题吗?
  • 为此,子弹基本上只是一个vector3 pos。我不需要旋转来指示前进的方向吗?
  • 假设玩家在 P 位置,敌人在 E 位置(P 和 E 都是 3D 向量),那么轨迹将是一个函数:T = E + t(PE),t 范围为 0到 1
  • 所以从技术上讲,我最好不要固执己见并修改我的 UpdateEnemyBulletPositions() 函数,以便仅使用您提到的函数而不是使用旋转作为方向?
  • 假设我确实想使用四分之一。我如何将所需的轨迹转换为四分之一,以便我的函数可以处理它?

标签: c# vector quaternions


【解决方案1】:

两点E和P之间的直线轨迹(代表敌人和玩家的3d向量)可以用以下公式计算:

T(t) = E + t*(P-E)

其中 t 是一个从 0 到 1 变化的系数(用于子弹动画)。

这是您可以构建的基础。但是,您可能希望子弹的射程有限。如果是这种情况,您可以执行以下操作:

  1. 计算子弹的方向:D = P-E
  2. 计算其长度:len = sqrt(Dx^2 + Dy^2 + Dz^2)。其中Dx为D等的x坐标,^2表示平方
  3. 标准化方向向量ND = (1/len)*D。 (只需将每个坐标除以len)

现在,在ND 中,您将有一个长度为 1 的向量,朝向敌人到玩家的方向。每次发射子弹时,都应该分配一个存储结构:

  • 当前ND
  • 子弹发射的位置(即E,敌人的当前位置)
  • 计数器 t = 0

在游戏的每个循环中,对于每个“活着”的子弹(以下是伪代码):

bullet.t += 1
if(bullet.t < maxNumberOfCyclesABulletLives){
  bPos = bullet.E + bullet.t * coefficient * bullet.ND // coefficient is the distance the bullet should move in each cycle
  if(bPos touches P){
    damageToPlayer()
    releaseTheStructureForThisBullet()
  }
  else drawBulletInPosition(bPos) // depending on your gaming library, you may have to erase it from the previous position
}
else{
  makeTheBulletExplode()
  releaseTheStructureForThisBullet() //or rather return it to a pool, where it can be reused
}

顺便说一句,你的游戏看起来很酷。一旦你发布它,我希望有一个免费的副本;-)

【讨论】:

  • 那么鉴于我在那个视频中的错误,你认为我的代码哪里出错了?另外我对计数器一无所知...
  • 我认为当您将子弹移动到新位置时,您可能没有擦除子弹。或者您可能正在生成子弹而不是摧毁它们。计数器,我的意思是一个整数变量,你在游戏的每个循环中递增 1。
  • 问题似乎是每个子弹都在前一个产生的地方产生。我费力地编写了代码,但我不知道为什么。
  • 也许敌方飞船正朝着子弹的方向向玩家移动?也许您没有开始新的子弹设置它的 t=0?
  • 如果 t 是从游戏时间派生的变量,我怎样才能让它总是从 0 开始?
猜你喜欢
  • 2012-06-11
  • 2016-05-05
  • 1970-01-01
  • 2013-03-30
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
  • 2020-03-16
  • 1970-01-01
相关资源
最近更新 更多