Figure out what keys a player is pressing based on relative velocity and angle

你离开我真会死。 提交于 2020-01-15 03:39:06

问题


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:

  1. is there inertia present (movement and / or rotation)?

    speed/direction changes immediately or slowly in time?

  2. Keys drive acceleration or velocity?

    speed/direction changes immediately or continuously in time with key press/hold/release?

  3. 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.

  1. so you need to have some update routine like timer with some dt interval
  2. remove frictions from v,omega if present

    just multiply the speed by inverse of friction to obtain original speed... This must be done before acceleration computation !!!

  3. compute acceleration a,epsilon from speed v,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 and dt is time step of your update routine. The a(t) means actual value and a(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.

  4. remove forcefields from a if present

    for 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

  5. 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 of a 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!