【问题标题】:Figure out what keys a player is pressing based on relative velocity and angle根据相对速度和角度找出玩家正在按下的键
【发布时间】:2016-06-11 17:08:11
【问题描述】:

我有两条信息:一个表示相对于网格的速度的 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)

但这并没有给我很好的结果,似乎它们与原始速度向量有点相同。

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

【问题讨论】:

  • 你不能只拥有速度——你还需要加速度(用于状态变化)
  • @willywonkadailyblah 等等,为什么?状态变化是什么意思?
  • 抱歉方向变了,所以键状态变了
  • 好的,但是我应该在哪里加入加速? (获取它们不是问题,我只是不明白在这种情况下如何处理加速度向量)
  • 如果你正以某种速度向某个方向移动,例如左。那么一个简单的解决方案就是A键。但是您也可能正在减速,即按 D,或以恒定速度 - 没有按下任何键(假设没有摩擦)。因此,如果您不考虑加速度,您将获得不确定的结果

标签: c# math rotation geometry 2d


【解决方案1】:

首先我们需要了解更多关于物理的知识,例如:

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

    速度/方向会立即改变还是慢慢改变?

  2. 按键驱动加速度还是速度?

    速度/方向会随着按键的按下/保持/释放立即或持续变化?

  3. 有摩擦吗?

    如果在一段时间后没有按任何键或立即或从不按任何键,对象会停止?

现在如何攻击这个

初见

通常用于更新对象位置/方向/速度。剩下的就简单了……

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

  1. 因此您需要一些更新例程,例如带有一些 dt 间隔的计时器
  2. 从v,omega 中删除摩擦(如果存在)

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

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

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

          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 度,则应确保绝对结果始终小于或等于 180 度。

  4. 从a 中删除力场(如果存在)

    例如,如果你有重力存在......等减去它。唯一应该留在加速中的是击键驱动的加速颠簸

  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 作为时间函数的图表,并在键处于活动状态时从中读取值......所以你实际上会立即看到正确的值而不是猜测......

【讨论】:

  • 我必须承认这一点确实花了我一段时间。但是您的回答为我提供了实施此操作所需的所有信息。谢谢=)
猜你喜欢
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-16
  • 1970-01-01
  • 2014-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多