问题
I have two pieces of information: a 2D-vector representing velocity relative to a grid and an angle (180 to negative 180 degrees) representing the player's view-angle also relative to that grid, and I am from that trying to figure out what keys (W, A, S, D) the player is pressing with this information.
The thing that is giving me troubles are the fact that the player moves in respect to the view-angle. So if the player is looking 35 degrees relative to our grid and pressing forward (W), the player will move forward 35 degrees which gives the velocity a mixture of forward and right (D). Something to note is that the maximum speed that a player gets from pressing a key is 250 units/s in that direction. But the vector gets taken into some calculation with the view angle which yields the final movement-speed, and this is why I'm asking this question.
I basically want to cancel out the angle's impact on the velocity vector.
For this, I tried using a Rotation-matrix solution using the following formula:
x' = x*cos(angle) - y*sin(angle)
y' = x*sin(angle) + y*cos(angle)
but this didn't give me good results, it seems like they are kind of the same as the original velocity vector.
Does anybody know what I'm doing wrong here? Shouldn't I just be able to calculate these values using a rotation matrix?
回答1:
First we need to know more about the physics like:
is there inertia present (movement and / or rotation)?
speed/direction changes immediately or slowly in time?
Keys drive acceleration or velocity?
speed/direction changes immediately or continuously in time with key press/hold/release?
Are there any frictions?
object stops if not pressed any key after time or immediately or never?
Now how to attack this
First see
- Newton - D'Alembert physics for non relativistic speeds dictates this
- Newton - D'Alembert physics and force fields+frictions
which are usually used for update of object position/direction/speed. From that is the rest easy ...
For example lets assume keys drive acceleration,inertia is present,no frictions, and you got only position p
, orientation alpha
and speed v
info in 2D.
- so you need to have some update routine like timer with some
dt
interval remove frictions from
v,omega
if presentjust multiply the speed by inverse of friction to obtain original speed... This must be done before acceleration computation !!!
compute acceleration
a,epsilon
from speedv,omega
That is easy it is just derivation by time:
a(t)=( v(t)- v(t-dt))/dt epsilon(t)=(omega(t)-omega(t-dt))/dt
Where
t
is actual time anddt
is time step of your update routine. Thea(t)
means actual value anda(t-dt)
means previous value from last update. So if you got only position info instead you can do similarly: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
For angular delta
(alpha(t)-alpha(t-dt))
you should ensure that the abs result is always smaller or equal then 180 degrees if not add/remove 360 degrees until it is.remove forcefields from
a
if presentfor example if you got gravity present ... etc subbstract it. The only thing that should be left in the accelerations is the key strokes driven acceleration bumps
decode keystrokes
That is easy for example if you movement schema is like turn left/right and move forward/backward then just extract the info (+/- your coordinate system corrections). The turning is directly visible in angular acceleration
epsilon
:if (epsilon>+ang_treshold) `D` is pressed; // turn left if (epsilon<-ang_treshold) `A` is pressed; // turn right
Now you just convert your movement acceleration
a
into orientation so it became local to you object by dot product with LCS (local coordinate system) axises:lcs_a.x=(a.x*cos(alpha ))+(a.y*sin(alpha )); lcs_a.y=(a.x*cos(alpha-90deg))+(a.y*sin(alpha-90deg));
And similarly investigate the bumps...
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
If your simulation is driven by speed then you will just investigate speed instead of acceleration in the same manner. The tresholds should be smaller but close to the actual key strokes acceleration bumps to avoid miss registration of some forgotten friction or what ever ... for start you can use
0
and if wrongly detected keystrokes then increase it a bit ... Safest way would be draw a graph ofa
as a function of time and read the values from it while key is active ... so you actually see the right value immediately instead of guessing ...
来源:https://stackoverflow.com/questions/37766419/figure-out-what-keys-a-player-is-pressing-based-on-relative-velocity-and-angle