根据相对速度和角度计算出玩家按下的按键

时间:2016-06-11 17:08:12

标签: c# math rotation geometry 2d

我有两条信息:一个2D矢量表示相对于网格的速度和一个角度(180到负180度),表示玩家的视角也相对于该网格,我来自试图找出玩家用这些信息按下的键(W,A,S,D)。

让我烦恼的是玩家相对于视角移动的事实。因此,如果玩家相对于我们的网格看向35度并且向前按压(W),则玩家将向前移动35度,这使得速度向前和向右混合(D)。 值得注意的是,玩家通过按键获得的最大速度是250个单位/秒。但是矢量会被视角进行一些计算,从而产生最终的移动速度,这就是我提出这个问题的原因。

我基本上想要消除角度对速度矢量的影响。

为此,我尝试使用以下公式的旋转矩阵解决方案:

x' =  x*cos(angle) - y*sin(angle)
y' =  x*sin(angle) + y*cos(angle)

但这并没有给我带来好结果,看起来它们与原始速度矢量有点相同。

有人知道我在这里做错了什么吗?难道我不能用旋转矩阵计算这些值吗?

1 个答案:

答案 0 :(得分:1)

首先,我们需要了解更多有关物理的信​​息,如:

  1. 是否存在惯性(移动和/或旋转)?

    速度/方向是否立即或缓慢变化?

  2. 键驱动加速度或速度?

    按键/按住/释放时,速度/方向是否立即或连续变化?

  3. 有没有摩擦?

    如果没有按任何键,对象会立即停止或立即或从不停止?

  4. 现在如何攻击

    首先看

    通常用于更新物体位置/方向/速度。从那以后,其余的很容易......

    例如,假设键驱动加速度,惯性存在,没有摩擦,并且您在2D中仅获得位置p,方向alpha和速度v信息。

    1. 所以你需要有一些更新例程,比如定时器有一些dt间隔
    2. v,omega中删除摩擦

      将速度乘以摩擦力的倒数以获得原始速度...... 这必须在加速度计算之前完成!!!

    3. 从速度a,epsilon计算加速v,omega

      这很容易,只是按时间推导出来:

            a(t)=(    v(t)-    v(t-dt))/dt
      epsilon(t)=(omega(t)-omega(t-dt))/dt
      

      t是实际时间,dt是更新例程的时间步长。 a(t)表示实际值,a(t-dt)表示上次更新的上一个值。因此,如果您只获得位置信息,则可以执行类似操作:

      v(t)=(p(t)-p(t-dt))/dt
      a(t)=(v(t)-v(t-dt))/dt
        omega(t)=(alpha(t)-alpha(t-dt))/dt
      epsilon(t)=(omega(t)-omega(t-dt))/dt
      

      对于角度增量(alpha(t)-alpha(t-dt)),如果不添加/删除360度,则应确保abs结果始终小于或等于180度。

    4. a移除强制分段

      例如,如果你有重力存在...等subbstract它。在加速度中唯一应该留下的是击键加速凸起

    5. 解码击键

      这很容易,例如,如果您的移动模式类似于向左/向右转动并向前/向后移动,那么只需提取信息(+/-您的坐标系更正)。在角加速度epsilon中可以直接看到转弯:

      if (epsilon>+ang_treshold) `D` is pressed; // turn left
      if (epsilon<-ang_treshold) `A` is pressed; // turn right
      

      现在,您只需将移动加速度a转换为方向,即通过带有LCS(局部坐标系)轴的点积来对您进行对象:

      lcs_a.x=(a.x*cos(alpha      ))+(a.y*sin(alpha      ));
      lcs_a.y=(a.x*cos(alpha-90deg))+(a.y*sin(alpha-90deg));
      

      同样调查颠簸......

      if (lcs_a.y>+mov_treshold) `W` is pressed; // move forward
      if (lcs_a.y<-mov_treshold) `S` is pressed; // move backward
      if (lcs_a.x>+mov_treshold) `E` is pressed; // move right 
      if (lcs_a.x<-mov_treshold) `Q` is pressed; // move left
      

      如果您的模拟是由速度驱动的,那么您将以相同的方式调查速度而不是加速度。阈值应该更小,但接近实际的键击加速度颠簸,以避免错过一些被遗忘的摩擦的记录,或者是什么......开始时你可以使用0,如果错误地检测到击键,那么增加一点......最安全的方法是绘制a作为时间函数的图形,并在键激活时从中读取值...所以你实际上会立即看到正确的值,而不是猜测......