根据相对速度和角度找出玩家按下的键
Figure out what keys a player is pressing based on relative velocity and angle
我有两条信息:一个 2D 向量表示相对于网格的速度和一个角度(180 到负 180 度)表示玩家的视角也相对于该网格,我来自那个尝试找出玩家使用此信息按下的键(W、A、S、D)。
给我带来麻烦的是玩家根据视角移动。因此,如果玩家相对于我们的网格看 35 度并向前按 (W),则玩家将向前移动 35 度,这会产生向前和向右混合的速度 (D)。
需要注意的是,玩家通过按键获得的最大速度是 250 units/s 在那个方向。但是矢量会被纳入一些计算,其中的视角会产生最终的移动速度,这就是我问这个问题的原因。
我基本上是想抵消角度对速度矢量的影响。
为此,我尝试使用使用以下公式的旋转矩阵解决方案:
x' = x*cos(angle) - y*sin(angle)
y' = x*sin(angle) + y*cos(angle)
但这并没有给我很好的结果,看起来它们与原始速度矢量有点相同。
有人知道我做错了什么吗?我不应该只使用旋转矩阵来计算这些值吗?
首先我们需要了解更多物理学知识,例如:
是否存在惯性(运动和/或旋转)?
speed/direction 随时间变化是立即变化还是缓慢变化?
按键驱动加速度还是速度?
speed/direction 随键 press/hold/release?
立即或连续变化
有没有摩擦?
如果在一段时间后没有按下任何键或立即或从不按下任何键,对象将停止?
现在如何攻击这个
初见
- Newton - D'Alembert physics for non relativistic speeds dictates this
- Newton - D'Alembert physics and force fields+frictions
通常用于更新对象position/direction/speed。从那以后就很容易了...
例如,假设按键驱动加速,存在惯性,没有摩擦,并且您在 2D 中只有位置 p
、方向 alpha
和速度 v
信息。
- 所以你需要一些更新例程,比如带有一些
dt
间隔的定时器
从 v,omega
中移除摩擦(如果存在)
只需将速度乘以摩擦力的倒数即可得到原始速度...这必须在加速度计算之前完成!!!
根据速度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
对于 angular delta (alpha(t)-alpha(t-dt))
你应该确保 abs 结果总是小于或等于 180 度,如果不是 add/remove 360 度直到它是。
从 a
移除力场(如果存在)
例如,如果你有重力存在......等减去它。唯一应该留在加速度中的是击键驱动的加速度颠簸
解码击键
这很容易,例如,如果您的移动架构类似于转动 left/right 并移动 forward/backward,那么只需提取信息(+/- 您的坐标系校正)。在angular加速度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
作为时间函数的图表,并在键处于活动状态时从中读取值...这样您实际上会立即看到正确的值,而不是猜测 ...
我有两条信息:一个 2D 向量表示相对于网格的速度和一个角度(180 到负 180 度)表示玩家的视角也相对于该网格,我来自那个尝试找出玩家使用此信息按下的键(W、A、S、D)。
给我带来麻烦的是玩家根据视角移动。因此,如果玩家相对于我们的网格看 35 度并向前按 (W),则玩家将向前移动 35 度,这会产生向前和向右混合的速度 (D)。 需要注意的是,玩家通过按键获得的最大速度是 250 units/s 在那个方向。但是矢量会被纳入一些计算,其中的视角会产生最终的移动速度,这就是我问这个问题的原因。
我基本上是想抵消角度对速度矢量的影响。
为此,我尝试使用使用以下公式的旋转矩阵解决方案:
x' = x*cos(angle) - y*sin(angle)
y' = x*sin(angle) + y*cos(angle)
但这并没有给我很好的结果,看起来它们与原始速度矢量有点相同。
有人知道我做错了什么吗?我不应该只使用旋转矩阵来计算这些值吗?
首先我们需要了解更多物理学知识,例如:
是否存在惯性(运动和/或旋转)?
speed/direction 随时间变化是立即变化还是缓慢变化?
按键驱动加速度还是速度?
speed/direction 随键 press/hold/release?
立即或连续变化
有没有摩擦?
如果在一段时间后没有按下任何键或立即或从不按下任何键,对象将停止?
现在如何攻击这个
初见
- Newton - D'Alembert physics for non relativistic speeds dictates this
- Newton - D'Alembert physics and force fields+frictions
通常用于更新对象position/direction/speed。从那以后就很容易了...
例如,假设按键驱动加速,存在惯性,没有摩擦,并且您在 2D 中只有位置 p
、方向 alpha
和速度 v
信息。
- 所以你需要一些更新例程,比如带有一些
dt
间隔的定时器 从
v,omega
中移除摩擦(如果存在)只需将速度乘以摩擦力的倒数即可得到原始速度...这必须在加速度计算之前完成!!!
根据速度
计算加速度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
对于 angular delta
(alpha(t)-alpha(t-dt))
你应该确保 abs 结果总是小于或等于 180 度,如果不是 add/remove 360 度直到它是。从
a
移除力场(如果存在)例如,如果你有重力存在......等减去它。唯一应该留在加速度中的是击键驱动的加速度颠簸
解码击键
这很容易,例如,如果您的移动架构类似于转动 left/right 并移动 forward/backward,那么只需提取信息(+/- 您的坐标系校正)。在angular加速度
中直接可见转弯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
作为时间函数的图表,并在键处于活动状态时从中读取值...这样您实际上会立即看到正确的值,而不是猜测 ...