C#矢量到四元数旋转问题

时间:2012-10-13 09:30:15

标签: c# vector quaternions

我有一个相当错综复杂的问题。基本上,我有一个跟踪玩家位置的物体,使用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开始计数器。

1 个答案:

答案 0 :(得分:0)

两点E和P之间的线性轨迹(代表敌人和玩家的三维矢量)可以用以下公式计算:

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
  4. 现在,在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
    }
    

    顺便说一句,你的游戏看起来很酷。我希望你发布它后可以获得免费副本; - )